summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.gitignore16
-rw-r--r--.gitmodules3
-rw-r--r--TOUR.729
-rw-r--r--agpl.c20
-rw-r--r--bin/.gitignore37
-rw-r--r--bin/LICENSE661
-rw-r--r--bin/Makefile153
-rw-r--r--bin/README.787
-rw-r--r--bin/beef.c141
-rw-r--r--bin/bibsort.pl68
-rw-r--r--bin/bit.y202
-rw-r--r--bin/bri.c85
-rw-r--r--bin/c.sh121
-rw-r--r--bin/c11.l149
-rw-r--r--bin/dash/.gitignore34
-rw-r--r--bin/dash/COPYING56
-rw-r--r--bin/dash/ChangeLog806
-rw-r--r--bin/dash/ChangeLog.O1023
-rw-r--r--bin/dash/Makefile.am1
-rw-r--r--bin/dash/Makefile.in776
-rw-r--r--bin/dash/aclocal.m41132
-rwxr-xr-xbin/dash/autogen.sh6
-rwxr-xr-xbin/dash/compile348
-rw-r--r--bin/dash/config.h.in205
-rwxr-xr-xbin/dash/configure6450
-rw-r--r--bin/dash/configure.ac194
-rwxr-xr-xbin/dash/depcomp791
-rwxr-xr-xbin/dash/install-sh541
-rwxr-xr-xbin/dash/missing215
-rw-r--r--bin/dash/src/.gitignore13
-rw-r--r--bin/dash/src/Makefile.am70
-rw-r--r--bin/dash/src/Makefile.in834
-rw-r--r--bin/dash/src/TOUR343
-rw-r--r--bin/dash/src/alias.c227
-rw-r--r--bin/dash/src/alias.h52
-rw-r--r--bin/dash/src/arith_yacc.c304
-rw-r--r--bin/dash/src/arith_yacc.h89
-rw-r--r--bin/dash/src/arith_yylex.c240
-rw-r--r--bin/dash/src/bltin/bltin.h89
-rw-r--r--bin/dash/src/bltin/echo.1109
-rw-r--r--bin/dash/src/bltin/printf.1354
-rw-r--r--bin/dash/src/bltin/printf.c478
-rw-r--r--bin/dash/src/bltin/test.1309
-rw-r--r--bin/dash/src/bltin/test.c700
-rw-r--r--bin/dash/src/bltin/times.c42
-rw-r--r--bin/dash/src/builtins.def.in94
-rw-r--r--bin/dash/src/cd.c332
-rw-r--r--bin/dash/src/cd.h35
-rw-r--r--bin/dash/src/dash.12361
-rw-r--r--bin/dash/src/error.c238
-rw-r--r--bin/dash/src/error.h129
-rw-r--r--bin/dash/src/eval.c1147
-rw-r--r--bin/dash/src/eval.h65
-rw-r--r--bin/dash/src/exec.c908
-rw-r--r--bin/dash/src/exec.h84
-rw-r--r--bin/dash/src/expand.c1753
-rw-r--r--bin/dash/src/expand.h83
-rw-r--r--bin/dash/src/funcs/cmv47
-rw-r--r--bin/dash/src/funcs/dirs71
-rw-r--r--bin/dash/src/funcs/kill47
-rw-r--r--bin/dash/src/funcs/login36
-rw-r--r--bin/dash/src/funcs/newgrp35
-rw-r--r--bin/dash/src/funcs/popd71
-rw-r--r--bin/dash/src/funcs/pushd71
-rw-r--r--bin/dash/src/funcs/suspend39
-rw-r--r--bin/dash/src/histedit.c504
-rw-r--r--bin/dash/src/init.h40
-rw-r--r--bin/dash/src/input.c498
-rw-r--r--bin/dash/src/input.h101
-rw-r--r--bin/dash/src/jobs.c1545
-rw-r--r--bin/dash/src/jobs.h113
-rw-r--r--bin/dash/src/machdep.h47
-rw-r--r--bin/dash/src/mail.c115
-rw-r--r--bin/dash/src/mail.h38
-rw-r--r--bin/dash/src/main.c363
-rw-r--r--bin/dash/src/main.h54
-rw-r--r--bin/dash/src/memalloc.c300
-rw-r--r--bin/dash/src/memalloc.h101
-rw-r--r--bin/dash/src/miscbltin.c506
-rw-r--r--bin/dash/src/miscbltin.h31
-rw-r--r--bin/dash/src/mkbuiltins120
-rw-r--r--bin/dash/src/mkinit.c493
-rw-r--r--bin/dash/src/mknodes.c448
-rw-r--r--bin/dash/src/mksignames.c417
-rw-r--r--bin/dash/src/mksyntax.c315
-rw-r--r--bin/dash/src/mktokens97
-rw-r--r--bin/dash/src/myhistedit.h46
-rw-r--r--bin/dash/src/mystring.c257
-rw-r--r--bin/dash/src/mystring.h63
-rw-r--r--bin/dash/src/nodes.c.pat166
-rw-r--r--bin/dash/src/nodetypes151
-rw-r--r--bin/dash/src/options.c558
-rw-r--r--bin/dash/src/options.h86
-rw-r--r--bin/dash/src/output.c429
-rw-r--r--bin/dash/src/output.h126
-rw-r--r--bin/dash/src/parser.c1677
-rw-r--r--bin/dash/src/parser.h103
-rw-r--r--bin/dash/src/redir.c483
-rw-r--r--bin/dash/src/redir.h52
-rw-r--r--bin/dash/src/shell.h104
-rw-r--r--bin/dash/src/show.c406
-rw-r--r--bin/dash/src/show.h45
-rw-r--r--bin/dash/src/system.c199
-rw-r--r--bin/dash/src/system.h118
-rw-r--r--bin/dash/src/trap.c446
-rw-r--r--bin/dash/src/trap.h57
-rw-r--r--bin/dash/src/var.c676
-rw-r--r--bin/dash/src/var.h173
-rw-r--r--bin/dtch.c271
-rw-r--r--bin/ever.c119
-rw-r--r--bin/fbatt.c123
-rw-r--r--bin/fbclock.c132
-rw-r--r--bin/freecell.c388
-rw-r--r--bin/glitch.c538
-rw-r--r--bin/hilex.c391
-rw-r--r--bin/hilex.h50
-rw-r--r--bin/htagml.c207
-rw-r--r--bin/html.mk45
-rw-r--r--bin/html.sh65
-rw-r--r--bin/make.l132
-rw-r--r--bin/man1/beef.191
-rw-r--r--bin/man1/bibsort.140
-rw-r--r--bin/man1/bit.155
-rw-r--r--bin/man1/bri.144
-rw-r--r--bin/man1/c.145
-rw-r--r--bin/man1/dtch.167
-rw-r--r--bin/man1/ever.151
-rw-r--r--bin/man1/fbatt.134
-rw-r--r--bin/man1/fbclock.136
-rw-r--r--bin/man1/glitch.177
-rw-r--r--bin/man1/hilex.1218
-rw-r--r--bin/man1/htagml.169
-rw-r--r--bin/man1/modem.131
-rw-r--r--bin/man1/mtags.176
-rw-r--r--bin/man1/nudge.144
-rw-r--r--bin/man1/order.138
-rw-r--r--bin/man1/pbd.166
-rw-r--r--bin/man1/pngo.156
-rw-r--r--bin/man1/psf2png.153
-rw-r--r--bin/man1/psfed.1166
-rw-r--r--bin/man1/ptee.140
-rw-r--r--bin/man1/relay.148
-rw-r--r--bin/man1/scheme.159
-rw-r--r--bin/man1/shotty.192
-rw-r--r--bin/man1/sup.148
-rw-r--r--bin/man1/title.151
-rw-r--r--bin/man1/typer.174
-rw-r--r--bin/man1/up.180
-rw-r--r--bin/man1/when.176
-rw-r--r--bin/man1/xx.168
-rw-r--r--bin/man3/png.390
-rw-r--r--bin/man6/freecell.650
-rw-r--r--bin/mdoc.l65
-rw-r--r--bin/modem.c102
-rw-r--r--bin/mtags.c99
-rw-r--r--bin/nudge.c78
-rw-r--r--bin/order.y195
-rw-r--r--bin/pbd.c151
-rw-r--r--bin/png.h108
-rw-r--r--bin/pngo.c812
-rw-r--r--bin/psf2png.c107
-rw-r--r--bin/psfed.c577
-rw-r--r--bin/ptee.c116
-rw-r--r--bin/relay.c218
-rw-r--r--bin/scheme.c278
-rw-r--r--bin/sh.l178
-rw-r--r--bin/shotty.c648
-rw-r--r--bin/sup.sh169
-rw-r--r--bin/title.c211
-rw-r--r--bin/typer.c197
-rw-r--r--bin/up.sh80
-rw-r--r--bin/when.y250
-rw-r--r--bin/xx.c142
-rw-r--r--doc/pdf/.gitignore1
-rw-r--r--doc/pdf/Makefile31
-rw-r--r--doc/rfc/.gitignore2
-rw-r--r--doc/rfc/Makefile38
-rw-r--r--doc/rfc/rfc.153
-rw-r--r--doc/rfc/rfc.in19
-rw-r--r--doc/rfc/rfctags.pl21
-rw-r--r--doc/zlib/Makefile87
-rw-r--r--doc/zlib/adler32.365
-rw-r--r--doc/zlib/adler32_combine.363
-rw-r--r--doc/zlib/compress.384
-rw-r--r--doc/zlib/compressBound.344
-rw-r--r--doc/zlib/crc32.366
-rw-r--r--doc/zlib/crc32_combine.354
-rw-r--r--doc/zlib/deflate.3370
-rw-r--r--doc/zlib/deflateBound.371
-rw-r--r--doc/zlib/deflateCopy.366
-rw-r--r--doc/zlib/deflateEnd.350
-rw-r--r--doc/zlib/deflateGetDictionary.379
-rw-r--r--doc/zlib/deflateInit.3178
-rw-r--r--doc/zlib/deflateInit2.3227
-rw-r--r--doc/zlib/deflateParams.3123
-rw-r--r--doc/zlib/deflatePending.356
-rw-r--r--doc/zlib/deflatePrime.364
-rw-r--r--doc/zlib/deflateReset.357
-rw-r--r--doc/zlib/deflateSetDictionary.3142
-rw-r--r--doc/zlib/deflateSetHeader.3180
-rw-r--r--doc/zlib/deflateTune.370
-rw-r--r--doc/zlib/gzbuffer.359
-rw-r--r--doc/zlib/gzclose.397
-rw-r--r--doc/zlib/gzdirect.385
-rw-r--r--doc/zlib/gzeof.363
-rw-r--r--doc/zlib/gzerror.375
-rw-r--r--doc/zlib/gzflush.373
-rw-r--r--doc/zlib/gzfread.3107
-rw-r--r--doc/zlib/gzfwrite.375
-rw-r--r--doc/zlib/gzgetc.355
-rw-r--r--doc/zlib/gzgets.367
-rw-r--r--doc/zlib/gzoffset.351
-rw-r--r--doc/zlib/gzopen.3261
-rw-r--r--doc/zlib/gzprintf.371
-rw-r--r--doc/zlib/gzputc.343
-rw-r--r--doc/zlib/gzputs.341
-rw-r--r--doc/zlib/gzread.3115
-rw-r--r--doc/zlib/gzseek.3108
-rw-r--r--doc/zlib/gzsetparams.351
-rw-r--r--doc/zlib/gzungetc.367
-rw-r--r--doc/zlib/gzwrite.339
-rw-r--r--doc/zlib/inflate.3398
-rw-r--r--doc/zlib/inflateBack.3285
-rw-r--r--doc/zlib/inflateBackEnd.343
-rw-r--r--doc/zlib/inflateBackInit.384
-rw-r--r--doc/zlib/inflateCopy.359
-rw-r--r--doc/zlib/inflateEnd.344
-rw-r--r--doc/zlib/inflateGetDictionary.369
-rw-r--r--doc/zlib/inflateGetHeader.3170
-rw-r--r--doc/zlib/inflateInit.3101
-rw-r--r--doc/zlib/inflateInit2.3181
-rw-r--r--doc/zlib/inflateMark.388
-rw-r--r--doc/zlib/inflatePrime.373
-rw-r--r--doc/zlib/inflateReset.381
-rw-r--r--doc/zlib/inflateSetDictionary.385
-rw-r--r--doc/zlib/inflateSync.372
-rw-r--r--doc/zlib/uncompress.392
-rw-r--r--doc/zlib/zlibCompileFlags.3163
-rw-r--r--doc/zlib/zlibVersion.345
-rw-r--r--etc/CodeQWERTY.bundle/Contents/Info.plist19
-rw-r--r--etc/CodeQWERTY.bundle/Contents/Resources/CodeQWERTY.keylayout1178
-rw-r--r--etc/Dark.terminal1652
-rw-r--r--etc/Go-Mono-Bold-Italic.ttfbin0 -> 176832 bytes
-rw-r--r--etc/Go-Mono-Bold.ttfbin0 -> 168340 bytes
-rw-r--r--etc/Go-Mono-Italic.ttfbin0 -> 173548 bytes
-rw-r--r--etc/Go-Mono.ttfbin0 -> 164200 bytes
-rw-r--r--etc/README.Go-Mono36
-rw-r--r--etc/code.map20
-rw-r--r--etc/psf/.gitignore2
-rw-r--r--etc/psf/Makefile24
-rw-r--r--etc/psf/default.u259
-rw-r--r--etc/psf/sans6x10.psfbin0 -> 2592 bytes
-rw-r--r--etc/psf/sans6x12.psfbin0 -> 3104 bytes
-rw-r--r--etc/psf/sans6x8.psfbin0 -> 2080 bytes
-rw-r--r--etc/wsconsctl.conf26
-rw-r--r--filter.c457
-rw-r--r--filters/email-gravatar.lua35
-rw-r--r--filters/email-libravatar.lua36
-rw-r--r--filters/file-authentication.lua359
-rw-r--r--filters/gentoo-ldap-authentication.lua360
-rw-r--r--filters/owner-example.lua17
-rw-r--r--filters/simple-authentication.lua314
m---------git0
-rw-r--r--gpl.c20
-rw-r--r--home/.config/X/modmap16
-rw-r--r--home/.config/X/resources49
-rw-r--r--home/.config/cwm/cwmrc87
-rw-r--r--home/.config/git/config24
-rw-r--r--home/.config/git/ignore2
-rw-r--r--home/.config/htop/htoprc29
-rw-r--r--home/.editrc1
-rw-r--r--home/.gdbinit1
-rw-r--r--home/.hushlogin0
-rw-r--r--home/.inputrc1
-rw-r--r--home/.lldbinit1
-rwxr-xr-xhome/.local/bin/aes7
-rwxr-xr-xhome/.local/bin/clock17
-rwxr-xr-xhome/.local/bin/def47
-rwxr-xr-xhome/.local/bin/deg6
-rwxr-xr-xhome/.local/bin/git-password7
-rwxr-xr-xhome/.local/bin/mdate2
-rwxr-xr-xhome/.local/bin/nasd9
-rwxr-xr-xhome/.local/bin/notify-send9
-rwxr-xr-xhome/.local/bin/np7
-rwxr-xr-xhome/.local/bin/open18
-rwxr-xr-xhome/.local/bin/pbcopy11
-rwxr-xr-xhome/.local/bin/pbpaste11
-rwxr-xr-xhome/.local/bin/versions9
-rw-r--r--home/.profile23
-rw-r--r--home/.shrc63
-rw-r--r--home/.ssh/config18
-rw-r--r--home/.xsession12
-rw-r--r--install.sh54
-rw-r--r--link.sh23
-rw-r--r--port/caesar/.gitignore2
-rw-r--r--port/caesar/Makefile19
-rw-r--r--port/caesar/caesar.673
-rw-r--r--port/caesar/caesar.c159
-rw-r--r--port/caesar/rot13.sh33
-rw-r--r--port/cgram/.gitignore1
-rw-r--r--port/cgram/Makefile17
-rw-r--r--port/cgram/cgram.665
-rw-r--r--port/cgram/cgram.c344
-rw-r--r--port/cgram/pathnames.h30
-rw-r--r--port/ddate/.gitignore1
-rw-r--r--port/ddate/Makefile15
-rw-r--r--port/ddate/ddate.1117
-rw-r--r--port/ddate/ddate.c399
-rw-r--r--port/file2c/.gitignore1
-rw-r--r--port/file2c/Makefile15
-rw-r--r--port/file2c/file2c.175
-rw-r--r--port/file2c/file2c.c92
-rw-r--r--port/wcwidth/.gitignore3
-rw-r--r--port/wcwidth/COPYRIGHT190
-rw-r--r--port/wcwidth/Makefile27
-rw-r--r--port/wcwidth/nonspacing.h89
-rw-r--r--port/wcwidth/wcfix.in7
-rw-r--r--port/wcwidth/wcswidth.c8
-rw-r--r--port/wcwidth/wcwidth.c29
-rw-r--r--port/wcwidth/wide.h65
-rw-r--r--prune.sh7
-rw-r--r--tests/filters/dump.lua17
-rw-r--r--txt/.notemap3
-rw-r--r--txt/books.txt129
-rw-r--r--txt/music.txt285
-rw-r--r--txt/plan.726
-rw-r--r--txt/shows.txt32
-rw-r--r--txt/trouble-at-jinx-hotel.txt236
-rw-r--r--txt/tweets.txt32
-rw-r--r--www/causal.agency/.gitignore3
-rw-r--r--www/causal.agency/Makefile20
-rw-r--r--www/causal.agency/index.770
-rw-r--r--www/causal.agency/style.css23
-rw-r--r--www/git.causal.agency/.gitignore6
-rw-r--r--www/git.causal.agency/Makefile20
-rw-r--r--www/git.causal.agency/about-filter.sh15
-rw-r--r--www/git.causal.agency/cgit/.gitignore13
-rw-r--r--www/git.causal.agency/cgit/.mailmap (renamed from .mailmap)0
-rw-r--r--www/git.causal.agency/cgit/AUTHORS (renamed from AUTHORS)0
-rw-r--r--www/git.causal.agency/cgit/COPYING (renamed from COPYING)0
-rw-r--r--www/git.causal.agency/cgit/Makefile (renamed from Makefile)4
-rw-r--r--www/git.causal.agency/cgit/README (renamed from README)13
-rw-r--r--www/git.causal.agency/cgit/cache.c (renamed from cache.c)7
-rw-r--r--www/git.causal.agency/cgit/cache.h (renamed from cache.h)0
-rw-r--r--www/git.causal.agency/cgit/cgit.c (renamed from cgit.c)9
-rw-r--r--www/git.causal.agency/cgit/cgit.css (renamed from cgit.css)28
-rw-r--r--www/git.causal.agency/cgit/cgit.h (renamed from cgit.h)1
-rw-r--r--www/git.causal.agency/cgit/cgit.mk (renamed from cgit.mk)27
-rw-r--r--www/git.causal.agency/cgit/cgit.png (renamed from cgit.png)bin1366 -> 1366 bytes
-rw-r--r--www/git.causal.agency/cgit/cgitrc.5.txt (renamed from cgitrc.5.txt)34
-rw-r--r--www/git.causal.agency/cgit/cmd.c (renamed from cmd.c)0
-rw-r--r--www/git.causal.agency/cgit/cmd.h (renamed from cmd.h)0
-rw-r--r--www/git.causal.agency/cgit/configfile.c (renamed from configfile.c)0
-rw-r--r--www/git.causal.agency/cgit/configfile.h (renamed from configfile.h)0
-rwxr-xr-xwww/git.causal.agency/cgit/contrib/hooks/post-receive.agefile (renamed from contrib/hooks/post-receive.agefile)0
-rw-r--r--www/git.causal.agency/cgit/favicon.ico (renamed from favicon.ico)bin1078 -> 1078 bytes
-rw-r--r--www/git.causal.agency/cgit/filter.c222
-rwxr-xr-xwww/git.causal.agency/cgit/filters/about-formatting.sh (renamed from filters/about-formatting.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/filters/commit-links.sh (renamed from filters/commit-links.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/filters/email-gravatar.py (renamed from filters/email-gravatar.py)3
-rwxr-xr-xwww/git.causal.agency/cgit/filters/html-converters/man2html (renamed from filters/html-converters/man2html)0
-rwxr-xr-xwww/git.causal.agency/cgit/filters/html-converters/md2html (renamed from filters/html-converters/md2html)0
-rwxr-xr-xwww/git.causal.agency/cgit/filters/html-converters/rst2html (renamed from filters/html-converters/rst2html)0
-rwxr-xr-xwww/git.causal.agency/cgit/filters/html-converters/txt2html (renamed from filters/html-converters/txt2html)0
-rwxr-xr-xwww/git.causal.agency/cgit/filters/syntax-highlighting.py (renamed from filters/syntax-highlighting.py)0
-rwxr-xr-xwww/git.causal.agency/cgit/filters/syntax-highlighting.sh (renamed from filters/syntax-highlighting.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/gen-version.sh (renamed from gen-version.sh)0
-rw-r--r--www/git.causal.agency/cgit/html.c (renamed from html.c)2
-rw-r--r--www/git.causal.agency/cgit/html.h (renamed from html.h)0
-rw-r--r--www/git.causal.agency/cgit/parsing.c (renamed from parsing.c)0
-rw-r--r--www/git.causal.agency/cgit/robots.txt (renamed from robots.txt)1
-rw-r--r--www/git.causal.agency/cgit/scan-tree.c (renamed from scan-tree.c)0
-rw-r--r--www/git.causal.agency/cgit/scan-tree.h (renamed from scan-tree.h)0
-rw-r--r--www/git.causal.agency/cgit/shared.c (renamed from shared.c)0
-rw-r--r--www/git.causal.agency/cgit/tests/.gitignore (renamed from tests/.gitignore)0
-rw-r--r--www/git.causal.agency/cgit/tests/Makefile (renamed from tests/Makefile)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/filters/dump.sh (renamed from tests/filters/dump.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/setup.sh (renamed from tests/setup.sh)19
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0001-validate-git-versions.sh (renamed from tests/t0001-validate-git-versions.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0010-validate-html.sh (renamed from tests/t0010-validate-html.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0020-validate-cache.sh (renamed from tests/t0020-validate-cache.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0101-index.sh (renamed from tests/t0101-index.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0102-summary.sh (renamed from tests/t0102-summary.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0103-log.sh (renamed from tests/t0103-log.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0104-tree.sh (renamed from tests/t0104-tree.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0105-commit.sh (renamed from tests/t0105-commit.sh)6
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0106-diff.sh (renamed from tests/t0106-diff.sh)4
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0107-snapshot.sh (renamed from tests/t0107-snapshot.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0108-patch.sh (renamed from tests/t0108-patch.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0109-gitconfig.sh (renamed from tests/t0109-gitconfig.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0110-rawdiff.sh (renamed from tests/t0110-rawdiff.sh)0
-rwxr-xr-xwww/git.causal.agency/cgit/tests/t0111-filter.sh (renamed from tests/t0111-filter.sh)3
-rwxr-xr-xwww/git.causal.agency/cgit/tests/valgrind/bin/cgit (renamed from tests/valgrind/bin/cgit)0
-rw-r--r--www/git.causal.agency/cgit/ui-atom.c (renamed from ui-atom.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-atom.h (renamed from ui-atom.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-blame.c (renamed from ui-blame.c)4
-rw-r--r--www/git.causal.agency/cgit/ui-blame.h (renamed from ui-blame.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-blob.c (renamed from ui-blob.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-blob.h (renamed from ui-blob.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-clone.c (renamed from ui-clone.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-clone.h (renamed from ui-clone.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-commit.c (renamed from ui-commit.c)7
-rw-r--r--www/git.causal.agency/cgit/ui-commit.h (renamed from ui-commit.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-diff.c (renamed from ui-diff.c)30
-rw-r--r--www/git.causal.agency/cgit/ui-diff.h (renamed from ui-diff.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-log.c (renamed from ui-log.c)4
-rw-r--r--www/git.causal.agency/cgit/ui-log.h (renamed from ui-log.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-patch.c (renamed from ui-patch.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-patch.h (renamed from ui-patch.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-plain.c (renamed from ui-plain.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-plain.h (renamed from ui-plain.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-refs.c (renamed from ui-refs.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-refs.h (renamed from ui-refs.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-repolist.c (renamed from ui-repolist.c)4
-rw-r--r--www/git.causal.agency/cgit/ui-repolist.h (renamed from ui-repolist.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-shared.c (renamed from ui-shared.c)44
-rw-r--r--www/git.causal.agency/cgit/ui-shared.h (renamed from ui-shared.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-snapshot.c (renamed from ui-snapshot.c)3
-rw-r--r--www/git.causal.agency/cgit/ui-snapshot.h (renamed from ui-snapshot.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-ssdiff.c (renamed from ui-ssdiff.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-ssdiff.h (renamed from ui-ssdiff.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-stats.c (renamed from ui-stats.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-stats.h (renamed from ui-stats.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-summary.c (renamed from ui-summary.c)0
-rw-r--r--www/git.causal.agency/cgit/ui-summary.h (renamed from ui-summary.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-tag.c (renamed from ui-tag.c)4
-rw-r--r--www/git.causal.agency/cgit/ui-tag.h (renamed from ui-tag.h)0
-rw-r--r--www/git.causal.agency/cgit/ui-tree.c (renamed from ui-tree.c)40
-rw-r--r--www/git.causal.agency/cgit/ui-tree.h (renamed from ui-tree.h)0
-rw-r--r--www/git.causal.agency/cgitrc29
-rw-r--r--www/git.causal.agency/custom.css86
-rw-r--r--www/git.causal.agency/owner-filter.sh6
-rw-r--r--www/git.causal.agency/source-filter.sh25
-rw-r--r--www/temp.causal.agency/.gitignore1
-rw-r--r--www/temp.causal.agency/Makefile16
-rw-r--r--www/temp.causal.agency/up.c156
-rw-r--r--www/text.causal.agency/.gitignore3
-rw-r--r--www/text.causal.agency/001-make.7159
-rw-r--r--www/text.causal.agency/002-writing-mdoc.7138
-rw-r--r--www/text.causal.agency/003-pleasant-c.7120
-rw-r--r--www/text.causal.agency/004-uloc.764
-rw-r--r--www/text.causal.agency/005-testing-c.773
-rw-r--r--www/text.causal.agency/006-some-libs.796
-rw-r--r--www/text.causal.agency/007-cgit-setup.7271
-rw-r--r--www/text.causal.agency/008-how-irc.7193
-rw-r--r--www/text.causal.agency/009-casual-update.7127
-rw-r--r--www/text.causal.agency/010-irc-suite.7409
-rw-r--r--www/text.causal.agency/011-libretls.7220
-rw-r--r--www/text.causal.agency/012-inability.739
-rw-r--r--www/text.causal.agency/013-hot-tips.7156
-rw-r--r--www/text.causal.agency/014-using-vi.7135
-rw-r--r--www/text.causal.agency/015-reusing-tags.7155
-rw-r--r--www/text.causal.agency/016-using-openbsd.7505
-rw-r--r--www/text.causal.agency/017-unpasswords.7153
-rw-r--r--www/text.causal.agency/018-operating-systems.786
-rw-r--r--www/text.causal.agency/019-mailing-list.7287
-rw-r--r--www/text.causal.agency/020-c-style.7172
-rw-r--r--www/text.causal.agency/021-time-machine.7144
-rw-r--r--www/text.causal.agency/022-swans-are-dead.7164
-rw-r--r--www/text.causal.agency/Makefile47
-rw-r--r--www/text.causal.agency/feed.sh55
-rw-r--r--www/text.causal.agency/igp.149
-rw-r--r--www/text.causal.agency/igp.c143
463 files changed, 65802 insertions, 1782 deletions
diff --git a/.gitignore b/.gitignore
index 661df346..3bcf7b3f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,4 @@
-# Files I don't care to see in git-status/commit
-/cgit
-cgit.conf
-CGIT-CFLAGS
-VERSION
-cgitrc.5
-cgitrc.5.fo
-cgitrc.5.html
-cgitrc.5.pdf
-cgitrc.5.xml
-*.o
-*.d
+/build
+/clone
+/git
+/trash
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index 5c6ecb4f..00000000
--- a/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "git"]
-	url = https://git.kernel.org/pub/scm/git/git.git
-	path = git
diff --git a/TOUR.7 b/TOUR.7
new file mode 100644
index 00000000..2e77ffaa
--- /dev/null
+++ b/TOUR.7
@@ -0,0 +1,29 @@
+.Dd December 28, 2020
+.Dt TOUR 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm tour
+.Nd things that are here
+.
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa home/
+.Dq dotfiles
+.It Pa bin/
+utilities of varying utility
+.It Pa bin/dash/
+dash patched for interactive use
+.It Pa doc/rfc/
+scripts for reading IETF RFCs
+.It Pa doc/zlib/
+zlib documentation ported to
+.Xr mdoc 7
+.It Pa www/
+sources for causal.agency sites
+.It Pa www/git.causal.agency/cgit/
+patched cgit
+.It Pa port/wcwidth/
+.Xr wcwidth 3
+replacement for macOS
+.El
diff --git a/agpl.c b/agpl.c
new file mode 100644
index 00000000..a2aa950e
--- /dev/null
+++ b/agpl.c
@@ -0,0 +1,20 @@
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
diff --git a/bin/.gitignore b/bin/.gitignore
new file mode 100644
index 00000000..be0a8004
--- /dev/null
+++ b/bin/.gitignore
@@ -0,0 +1,37 @@
+*.html
+*.o
+beef
+bibsort
+bit
+bri
+c
+config.mk
+dtch
+ever
+fbatt
+fbclock
+freecell
+glitch
+hilex
+htagml
+htmltags
+modem
+mtags
+nudge
+order
+pbd
+pngo
+psf2png
+psfed
+ptee
+relay
+scheme
+scheme.h
+shotty
+sup
+tags
+title
+typer
+up
+when
+xx
diff --git a/bin/LICENSE b/bin/LICENSE
new file mode 100644
index 00000000..dba13ed2
--- /dev/null
+++ b/bin/LICENSE
@@ -0,0 +1,661 @@
+                    GNU AFFERO GENERAL PUBLIC LICENSE
+                       Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+  A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate.  Many developers of free software are heartened and
+encouraged by the resulting cooperation.  However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+  The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community.  It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server.  Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+  An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals.  This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU Affero General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Remote Network Interaction; Use with the GNU General Public License.
+
+  Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software.  This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time.  Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Affero General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU Affero General Public License for more details.
+
+    You should have received a copy of the GNU Affero General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source.  For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code.  There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
diff --git a/bin/Makefile b/bin/Makefile
new file mode 100644
index 00000000..14ad94eb
--- /dev/null
+++ b/bin/Makefile
@@ -0,0 +1,153 @@
+PREFIX ?= ~/.local
+MANDIR ?= ${PREFIX}/share/man
+
+LIBS_PREFIX ?= /usr/local
+CFLAGS += -I${LIBS_PREFIX}/include
+LDFLAGS += -L${LIBS_PREFIX}/lib
+
+CFLAGS += -Wall -Wextra -Wpedantic -Wno-gnu-case-range
+
+BINS += beef
+BINS += bibsort
+BINS += bit
+BINS += c
+BINS += dtch
+BINS += glitch
+BINS += hilex
+BINS += htagml
+BINS += modem
+BINS += mtags
+BINS += nudge
+BINS += order
+BINS += pbd
+BINS += pngo
+BINS += psf2png
+BINS += ptee
+BINS += scheme
+BINS += shotty
+BINS += sup
+BINS += title
+BINS += up
+BINS += when
+BINS += xx
+
+BSD += ever
+
+GAMES += freecell
+
+LINUX += bri
+LINUX += fbatt
+LINUX += fbclock
+LINUX += psfed
+
+TLS += relay
+TLS += typer
+
+MANS = ${BINS:%=man1/%.1}
+MANS.BSD = ${BSD:%=man1/%.1}
+MANS.GAMES = ${GAMES:%=man6/%.6}
+MANS.LINUX = ${LINUX:%=man1/%.1}
+MANS.TLS = ${TLS:%=man1/%.1}
+
+LDLIBS.dtch = -lutil
+LDLIBS.fbclock = -lz
+LDLIBS.freecell = -lcurses
+LDLIBS.glitch = -lz
+LDLIBS.modem = -lutil
+LDLIBS.pngo = -lz
+LDLIBS.ptee = -lutil
+LDLIBS.relay = -ltls
+LDLIBS.scheme = -lm
+LDLIBS.title = -lcurl
+LDLIBS.typer = -ltls
+
+ALL ?= meta any
+
+-include config.mk
+
+all: ${ALL}
+
+meta: .gitignore tags
+
+any: ${BINS}
+
+bsd: ${BSD}
+
+games: ${GAMES}
+
+linux: ${LINUX}
+
+tls: ${TLS}
+
+IGNORE = *.o *.html
+IGNORE += ${BINS} ${BSD} ${GAMES} ${LINUX} ${TLS}
+IGNORE += scheme.h tags htmltags
+
+.gitignore: Makefile
+	echo config.mk '${IGNORE}' | tr ' ' '\n' | sort > $@
+
+tags: *.[chly]
+	ctags -w *.[chly]
+
+clean:
+	rm -f ${IGNORE}
+
+install: ${ALL:%=install-%}
+
+install-meta:
+	install -d ${PREFIX}/bin ${MANDIR}/man1
+
+install-any: install-meta ${BINS} ${MANS}
+	install ${BINS} ${PREFIX}/bin
+	install -m 644 ${MANS} ${MANDIR}/man1
+
+install-bsd: install-meta ${BSD} ${MANS.BSD}
+	install ${BSD} ${PREFIX}/bin
+	install -m 644 ${MANS.BSD} ${MANDIR}/man1
+
+install-games: install-meta ${GAMES} ${MANS.GAMES}
+	install ${GAMES} ${PREFIX}/bin
+	install -m 644 ${MANS.GAMES} ${MANDIR}/man6
+
+install-linux: install-meta ${LINUX} ${MANS.LINUX}
+	install ${LINUX} ${PREFIX}/bin
+	install -m 644 ${MANS.LINUX} ${MANDIR}/man1
+
+install-tls: install-meta ${TLS} ${MANS.TLS}
+	install ${TLS} ${PREFIX}/bin
+	install -m 644 ${MANS.TLS} ${MANDIR}/man1
+
+uninstall:
+	rm -f ${BINS:%=${PREFIX}/bin/%} ${MANS:%=${MANDIR}/%}
+	rm -f ${BSD:%=${PREFIX}/bin/%} ${MANS.BSD:%=${MANDIR}/%}
+	rm -f ${GAMES:%=${PREFIX}/bin/%} ${MANS.GAMES:%=${MANDIR}/%}
+	rm -f ${LINUX:%=${PREFIX}/bin/%} ${MANS.LINUX:%=${MANDIR}/%}
+	rm -f ${TLS:%=${PREFIX}/bin/%} ${MANS.TLS:%=${MANDIR}/%}
+
+.SUFFIXES: .pl
+
+.c:
+	${CC} ${CFLAGS} ${LDFLAGS} $< ${LDLIBS.$@} -o $@
+
+.o:
+	${CC} ${LDFLAGS} $< ${LDLIBS.$@} -o $@
+
+.pl:
+	cp -f $< $@
+	chmod a+x $@
+
+OBJS.hilex = c11.o hilex.o make.o mdoc.o sh.o
+
+hilex: ${OBJS.hilex}
+	${CC} ${LDFLAGS} ${OBJS.$@} ${LDLIBS.$@} -o $@
+
+${OBJS.hilex}: hilex.h
+
+fbatt.o fbclock.o: scheme.h
+
+psf2png.o scheme.o: png.h
+
+scheme.h: scheme
+	./scheme -c > $@
+
+include html.mk
diff --git a/bin/README.7 b/bin/README.7
new file mode 100644
index 00000000..0ff46eab
--- /dev/null
+++ b/bin/README.7
@@ -0,0 +1,87 @@
+.Dd April 26, 2021
+.Dt BIN 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm bin
+.Nd various utilities
+.
+.Sh DESCRIPTION
+Various tools primarily targeting
+Darwin,
+.Fx
+and
+.Ox .
+Some tools target Linux.
+.
+.Pp
+.Bl -tag -width "fbclock(1)" -compact
+.It Xr beef 1
+Befunge-93 interpreter
+.It Xr bibsort 1
+reformat bibliography
+.It Xr bit 1
+calculator
+.It Xr bri 1
+backlight brightness control
+.It Xr c 1
+run C statements
+.It Xr dtch 1
+detached sessions
+.It Xr ever 1
+watch files
+.It Xr fbatt 1
+framebuffer battery indicator
+.It Xr fbclock 1
+framebuffer clock
+.It Xr freecell 6
+patience game
+.It Xr glitch 1
+PNG glitcher
+.It Xr hilex 1
+syntax highlighter
+.It Xr htagml 1
+tags HTMLizer
+.It Xr modem 1
+fixed baud rate wrapper
+.It Xr mtags 1
+miscellaneous tags
+.It Xr nudge 1
+terminal vibrator
+.It Xr order 1
+operator precedence
+.It Xr pbd 1
+macOS pasteboard daemon
+.It Xr pngo 1
+PNG optimizer
+.It Xr psf2png 1
+PSF2 to PNG renderer
+.It Xr psfed 1
+PSF2 font editor
+.It Xr ptee 1
+tee for PTYs
+.It Xr relay 1
+IRC relay bot
+.It Xr scheme 1
+color scheme
+.It Xr shotty 1
+terminal capture
+.It Xr sup 1
+single-use passwords
+.It Xr title 1
+page titles
+.It Xr up 1
+upload file
+.It Xr when 1
+date calculator
+.It Xr xx 1
+hexdump
+.El
+.
+.Pp
+One piece of reused code.
+.Pp
+.Bl -tag -width "png(3)" -compact
+.It Xr png 3
+basic PNG output
+.El
diff --git a/bin/beef.c b/bin/beef.c
new file mode 100644
index 00000000..556f3088
--- /dev/null
+++ b/bin/beef.c
@@ -0,0 +1,141 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+
+enum {
+	Cols = 80,
+	Rows = 25,
+};
+static char page[Rows][Cols];
+
+static char get(int y, int x) {
+	if (y < 0 || y >= Rows) return 0;
+	if (x < 0 || x >= Cols) return 0;
+	return page[y][x];
+}
+static void put(int y, int x, char v) {
+	if (y < 0 || y >= Rows) return;
+	if (x < 0 || x >= Cols) return;
+	page[y][x] = v;
+}
+
+enum { StackLen = 1024 };
+static long stack[StackLen];
+static size_t top = StackLen;
+
+static void push(long val) {
+	if (!top) errx(EX_SOFTWARE, "stack overflow");
+	stack[--top] = val;
+}
+static long pop(void) {
+	if (top == StackLen) return 0;
+	return stack[top++];
+}
+
+static struct {
+	int y, x;
+	int dy, dx;
+} pc = { .dx = 1 };
+
+static void inc(void) {
+	pc.y += pc.dy;
+	pc.x += pc.dx;
+	if (pc.y == -1) pc.y += Rows;
+	if (pc.x == -1) pc.x += Cols;
+	if (pc.y == Rows) pc.y -= Rows;
+	if (pc.x == Cols) pc.x -= Cols;
+}
+
+static bool string;
+
+static bool step(void) {
+	char ch = page[pc.y][pc.x];
+
+	if (ch == '"') {
+		string ^= true;
+	} else if (string) {
+		push(ch);
+		inc();
+		return true;
+	}
+
+	if (ch == '?') ch = "><^v"[rand() % 4];
+
+	long x, y, v;
+	switch (ch) {
+		break; case '+': push(pop() + pop());
+		break; case '-': y = pop(); x = pop(); push(x - y);
+		break; case '*': push(pop() * pop());
+		break; case '/': y = pop(); x = pop(); push(x / y);
+		break; case '%': y = pop(); x = pop(); push(x % y);
+		break; case '!': push(!pop());
+		break; case '`': y = pop(); x = pop(); push(x > y);
+		break; case '>': pc.dy = 0; pc.dx = +1;
+		break; case '<': pc.dy = 0; pc.dx = -1;
+		break; case '^': pc.dy = -1; pc.dx = 0;
+		break; case 'v': pc.dy = +1; pc.dx = 0;
+		break; case '_': pc.dy = 0; pc.dx = (pop() ? -1 : +1);
+		break; case '|': pc.dx = 0; pc.dy = (pop() ? -1 : +1);
+		break; case ':': x = pop(); push(x); push(x);
+		break; case '\\': y = pop(); x = pop(); push(y); push(x);
+		break; case '$': pop();
+		break; case '.': printf("%ld ", pop()); fflush(stdout);
+		break; case ',': printf("%c", (char)pop()); fflush(stdout);
+		break; case '#': inc();
+		break; case 'g': y = pop(); x = pop(); push(get(y, x));
+		break; case 'p': y = pop(); x = pop(); v = pop(); put(y, x, v);
+		break; case '&': x = EOF; scanf("%ld", &x); push(x);
+		break; case '~': push(getchar());
+		break; case '@': return false;
+		break; default:  if (ch >= '0' && ch <= '9') push(ch - '0');
+	}
+
+	inc();
+	return true;
+}
+
+int main(int argc, char *argv[]) {
+	srand(time(NULL));
+	memset(page, ' ', sizeof(page));
+
+	FILE *file = stdin;
+	if (argc > 1) {
+		file = fopen(argv[1], "r");
+		if (!file) err(EX_NOINPUT, "%s", argv[1]);
+	}
+
+	int y = 0;
+	char *line = NULL;
+	size_t cap = 0;
+	while (y < Rows && 0 < getline(&line, &cap, file)) {
+		for (int x = 0; x < Cols; ++x) {
+			if (line[x] == '\n' || !line[x]) break;
+			page[y][x] = line[x];
+		}
+		y++;
+	}
+	free(line);
+
+	while (step());
+	return pop();
+}
diff --git a/bin/bibsort.pl b/bin/bibsort.pl
new file mode 100644
index 00000000..0d132c19
--- /dev/null
+++ b/bin/bibsort.pl
@@ -0,0 +1,68 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+while (<>) {
+	print;
+	last if /^[.]Sh STANDARDS$/;
+}
+
+my ($ref, @refs);
+while (<>) {
+	next if /^[.](Bl|It|$)/;
+	last if /^[.]El$/;
+	if (/^[.]Rs$/) {
+		$ref = {};
+	} elsif (/^[.]%(.) (.*)/) {
+		$ref->{$1} = [] unless $ref->{$1};
+		push @{$ref->{$1}}, $2;
+	} elsif (/^[.]Re$/) {
+		push @refs, $ref;
+	} else {
+		print;
+	}
+}
+
+sub byLast {
+	my ($af, $al) = split /\s(\S+)(,.*)?$/, $a;
+	my ($bf, $bl) = split /\s(\S+)(,.*)?$/, $b;
+	($al // $af) cmp ($bl // $bf) || $af cmp $bf;
+}
+
+foreach $ref (@refs) {
+	@{$ref->{A}} = sort byLast @{$ref->{A}};
+	@{$ref->{Q}} = sort @{$ref->{Q}} if $ref->{Q};
+	if ($ref->{N} && $ref->{N}[0] =~ /RFC/) {
+		$ref->{R} = $ref->{N};
+		delete $ref->{N};
+	}
+	if ($ref->{R} && $ref->{R}[0] =~ /RFC (\d+)/ && !$ref->{U}) {
+		$ref->{U} = ["https://tools.ietf.org/html/rfc${1}"];
+	}
+}
+
+sub byAuthor {
+	local ($a, $b) = ($a->{A}[0], $b->{A}[0]);
+	byLast();
+}
+
+{
+	local ($,, $\) = (' ', "\n");
+	print '.Bl', '-item';
+	foreach $ref (sort byAuthor @refs) {
+		print '.It';
+		print '.Rs';
+		foreach my $key (qw(A T B I J R N V U P Q C D O)) {
+			next unless $ref->{$key};
+			foreach (@{$ref->{$key}}) {
+				print ".%${key}", $_;
+			}
+		}
+		print '.Re';
+	}
+	print '.El';
+}
+
+while (<>) {
+	print;
+}
diff --git a/bin/bit.y b/bin/bit.y
new file mode 100644
index 00000000..1119bce6
--- /dev/null
+++ b/bin/bit.y
@@ -0,0 +1,202 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%{
+
+#include <ctype.h>
+#include <err.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#define MASK(b) ((1ULL << (b)) - 1)
+
+#define YYSTYPE uint64_t
+
+static int yylex(void);
+static void yyerror(const char *str);
+static void print(uint64_t val);
+
+static uint64_t vars[128];
+
+%}
+
+%token Int Var
+
+%left '$'
+%right '='
+%left '|'
+%left '^'
+%left '&'
+%left Shl Shr Sar
+%left '+' '-'
+%left '*' '/' '%'
+%right '~'
+%left 'K' 'M' 'G' 'T'
+
+%%
+
+stmt:
+	| stmt expr '\n' { print(vars['_'] = $2); printf("\n"); }
+	| stmt expr ',' { print(vars['_'] = $2); }
+	| stmt '\n'
+	;
+
+expr:
+	Int
+	| Var { $$ = vars[$1]; }
+	| '(' expr ')' { $$ = $2; }
+	| expr 'K' { $$ = $1 << 10; }
+	| expr 'M' { $$ = $1 << 20; }
+	| expr 'G' { $$ = $1 << 30; }
+	| expr 'T' { $$ = $1 << 40; }
+	| '~' expr { $$ = ~$2; }
+	| '&' expr %prec '~' { $$ = MASK($2); }
+	| '+' expr %prec '~' { $$ = +$2; }
+	| '-' expr %prec '~' { $$ = -$2; }
+	| expr '*' expr { $$ = $1 * $3; }
+	| expr '/' expr { $$ = $1 / $3; }
+	| expr '%' expr { $$ = $1 % $3; }
+	| expr '+' expr { $$ = $1 + $3; }
+	| expr '-' expr { $$ = $1 - $3; }
+	| expr Shl expr { $$ = $1 << $3; }
+	| expr Shr expr { $$ = $1 >> $3; }
+	| expr Sar expr { $$ = (int64_t)$1 >> $3; }
+	| expr '&' expr { $$ = $1 & $3; }
+	| expr '^' expr { $$ = $1 ^ $3; }
+	| expr '|' expr { $$ = $1 | $3; }
+	| Var '=' expr { $$ = vars[$1] = $3; }
+	| expr '$' { $$ = $1; }
+	;
+
+%%
+
+static int lexInt(uint64_t base) {
+	yylval = 0;
+	for (int ch; EOF != (ch = getchar());) {
+		uint64_t digit = base;
+		if (ch == '_') {
+			continue;
+		} else if (isdigit(ch)) {
+			digit = ch - '0';
+		} else if (isxdigit(ch)) {
+			digit = 0xA + toupper(ch) - 'A';
+		}
+		if (digit >= base) {
+			ungetc(ch, stdin);
+			return Int;
+		}
+		yylval *= base;
+		yylval += digit;
+	}
+	return Int;
+}
+
+static int yylex(void) {
+	int ch;
+	while (isblank(ch = getchar()));
+	if (ch == '\'') {
+		yylval = 0;
+		while (EOF != (ch = getchar()) && ch != '\'') {
+			yylval <<= 8;
+			yylval |= ch;
+		}
+		return Int;
+	} else if (ch == '0') {
+		ch = getchar();
+		if (ch == 'b') {
+			return lexInt(2);
+		} else if (ch == 'x') {
+			return lexInt(16);
+		} else {
+			ungetc(ch, stdin);
+			return lexInt(8);
+		}
+	} else if (isdigit(ch)) {
+		ungetc(ch, stdin);
+		return lexInt(10);
+	} else if (ch == '_' || islower(ch)) {
+		yylval = ch;
+		return Var;
+	} else if (ch == '<') {
+		char ne = getchar();
+		if (ne == '<') {
+			return Shl;
+		} else {
+			ungetc(ne, stdin);
+			return ch;
+		}
+	} else if (ch == '-' || ch == '>') {
+		char ne = getchar();
+		if (ne == '>') {
+			return (ch == '-' ? Sar : Shr);
+		} else {
+			ungetc(ne, stdin);
+			return ch;
+		}
+	} else {
+		return ch;
+	}
+}
+
+static void yyerror(const char *str) {
+	warnx("%s", str);
+}
+
+static const char *Codes[128] = {
+	"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+	"BS",  "HT",  "NL",  "VT",  "NP",  "CR",  "SO",  "SI",
+	"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+	"CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US",
+	[127] = "DEL",
+};
+
+static void print(uint64_t val) {
+	int bits = val > UINT32_MAX ? 64
+		: val > UINT16_MAX ? 32
+		: val > UINT8_MAX ? 16
+		: 8;
+	printf("0x%0*"PRIX64" %"PRId64"", bits >> 2, val, (int64_t)val);
+	if (bits == 8) {
+		char bin[9] = {0};
+		for (int i = 0; i < 8; ++i) {
+			bin[i] = '0' + (val >> (7 - i) & 1);
+		}
+		printf(" %#"PRIo64" 0b%s", val, bin);
+	}
+	if (val < 128) {
+		if (isprint(val)) printf(" '%c'", (char)val);
+		if (Codes[val]) printf(" %s", Codes[val]);
+	}
+	if (val) {
+		if (!(val & MASK(40))) {
+			printf(" %"PRIu64"T", val >> 40);
+		} else if (!(val & MASK(30))) {
+			printf(" %"PRIu64"G", val >> 30);
+		} else if (!(val & MASK(20))) {
+			printf(" %"PRIu64"M", val >> 20);
+		} else if (!(val & MASK(10))) {
+			printf(" %"PRIu64"K", val >> 10);
+		}
+	}
+	printf("\n");
+}
+
+int main(void) {
+	while (yyparse());
+}
diff --git a/bin/bri.c b/bin/bri.c
new file mode 100644
index 00000000..c9bf6b0c
--- /dev/null
+++ b/bin/bri.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 2017  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+typedef unsigned uint;
+
+static const char *Class = "/sys/class/backlight";
+
+int main(int argc, char *argv[]) {
+	int error;
+
+	const char *input = (argc > 1) ? argv[1] : NULL;
+
+	error = chdir(Class);
+	if (error) err(EX_OSFILE, "%s", Class);
+
+	DIR *dir = opendir(".");
+	if (!dir) err(EX_OSFILE, "%s", Class);
+
+	struct dirent *entry;
+	while (NULL != (errno = 0, entry = readdir(dir))) {
+		if (entry->d_name[0] == '.') continue;
+
+		error = chdir(entry->d_name);
+		if (error) err(EX_OSFILE, "%s/%s", Class, entry->d_name);
+		break;
+	}
+	if (!entry) {
+		if (errno) err(EX_IOERR, "%s", Class);
+		errx(EX_CONFIG, "%s: empty", Class);
+	}
+
+	FILE *actual = fopen("actual_brightness", "r");
+	if (!actual) err(EX_OSFILE, "actual_brightness");
+
+	uint value;
+	int match = fscanf(actual, "%u", &value);
+	if (match == EOF) err(EX_IOERR, "actual_brightness");
+	if (match < 1) errx(EX_DATAERR, "actual_brightness");
+
+	if (!input) {
+		printf("%u\n", value);
+		return EX_OK;
+	}
+
+	if (input[0] == '+' || input[0] == '-') {
+		size_t count = strnlen(input, 16);
+		if (input[0] == '+') {
+			value += 16 * count;
+		} else {
+			value -= 16 * count;
+		}
+	} else {
+		value = strtoul(input, NULL, 0);
+	}
+
+	FILE *brightness = fopen("brightness", "w");
+	if (!brightness) err(EX_OSFILE, "brightness");
+
+	int size = fprintf(brightness, "%u", value);
+	if (size < 0) err(EX_IOERR, "brightness");
+
+	return EX_OK;
+}
diff --git a/bin/c.sh b/bin/c.sh
new file mode 100644
index 00000000..ff059437
--- /dev/null
+++ b/bin/c.sh
@@ -0,0 +1,121 @@
+#!/bin/sh
+set -eu
+
+temp=$(mktemp -d)
+trap 'rm -r "${temp}"' EXIT
+
+exec 3>>"${temp}/run.c"
+
+cat >&3 <<EOF
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <unistd.h>
+EOF
+
+expr=
+type=
+while getopts 'e:i:t' opt; do
+	case "${opt}" in
+		(e) expr=$OPTARG;;
+		(i) echo "#include <${OPTARG}>" >&3;;
+		(t) type=1;;
+		(?) exit 1;;
+	esac
+done
+shift $((OPTIND - 1))
+
+cat >&3 <<EOF
+int main(int argc, char *argv[]) {
+	(void)argc;
+	(void)argv;
+	$*;
+EOF
+
+if [ -n "${type}" ]; then
+	cat >&3 <<EOF
+	printf(
+		_Generic(
+			${expr},
+			char: "(char) ",
+			char *: "(char *) ",
+			const char *: "(const char *) ",
+			wchar_t *: "(wchar_t *) ",
+			const wchar_t *: "(const wchar_t *) ",
+			signed char: "(signed char) ",
+			short: "(short) ",
+			int: "(int) ",
+			long: "(long) ",
+			long long: "(long long) ",
+			unsigned char: "(unsigned char) ",
+			unsigned short: "(unsigned short) ",
+			unsigned int: "(unsigned int) ",
+			unsigned long: "(unsigned long) ",
+			unsigned long long: "(unsigned long long) ",
+			float: "(float) ",
+			double: "(double) ",
+			long double: "(long double) ",
+			default: "(void *) "
+		)
+	);
+EOF
+fi
+
+if [ -n "${expr}" ]; then
+	cat >&3 <<EOF
+	printf(
+		_Generic(
+			${expr},
+			char: "%c\n",
+			char *: "%s\n",
+			const char *: "%s\n",
+			wchar_t *: "%ls\n",
+			const wchar_t *: "%ls\n",
+			signed char: "%hhd\n",
+			short: "%hd\n",
+			int: "%d\n",
+			long: "%ld\n",
+			long long: "%lld\n",
+			unsigned char: "%hhu\n",
+			unsigned short: "%hu\n",
+			unsigned int: "%u\n",
+			unsigned long: "%lu\n",
+			unsigned long long: "%llu\n",
+			float: "%g\n",
+			double: "%g\n",
+			long double: "%Lg\n",
+			default: "%p\n"
+		),
+		${expr}
+	);
+EOF
+fi
+
+if [ $# -eq 0 -a -z "${expr}" ]; then
+	cat >&3
+fi
+
+echo '}' >&3
+
+cat >"${temp}/Makefile" <<EOF
+CFLAGS += -Wall -Wextra -Wpedantic
+EOF
+
+make -s -C "${temp}" run
+"${temp}/run"
diff --git a/bin/c11.l b/bin/c11.l
new file mode 100644
index 00000000..88e4d08b
--- /dev/null
+++ b/bin/c11.l
@@ -0,0 +1,149 @@
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%option prefix="c11"
+%option noyywrap
+
+%{
+#include "hilex.h"
+%}
+
+%s MacroLine MacroInclude
+%x CharLiteral StringLiteral
+
+ident [_[:alpha:]][_[:alnum:]]*
+width "*"|[0-9]+
+
+%%
+	static int pop = INITIAL;
+
+[[:blank:]]+ { return Normal; }
+
+^"%"[%{}]? {
+	BEGIN(pop = MacroLine);
+	return Macro;
+}
+
+([-+*/%&|^=!<>]|"<<"|">>")"="? |
+[=~.?:]|"["|"]"|"++"|"--"|"&&"|"||"|"->" |
+sizeof|(_A|alignof) {
+	return Operator;
+}
+
+([1-9][0-9]*|"0"[0-7]*|"0x"[[:xdigit:]]+)([ulUL]{0,3}) |
+([0-9]+("."[0-9]*)?|[0-9]*"."[0-9]+)([eE][+-]?[0-9]+)?[flFL]? |
+"0x"[[:xdigit:]]*("."[[:xdigit:]]*)?([pP][+-]?[0-9]+)[flFL]? {
+	return Number;
+}
+
+auto|break|case|const|continue|default|do|else|enum|extern|for|goto|if|inline |
+register|restrict|return|static|struct|switch|typedef|union|volatile|while |
+(_A|a)lignas|_Atomic|_Generic|(_N|n)oreturn|(_S|s)tatic_assert |
+(_T|t)hread_local {
+	return Keyword;
+}
+
+^"#"[[:blank:]]*(include|import) {
+	BEGIN(pop = MacroInclude);
+	return Macro;
+}
+^"#"[[:blank:]]*{ident} {
+	BEGIN(pop = MacroLine);
+	return Macro;
+}
+<MacroInclude>"<"[^>]+">" {
+	return String;
+}
+<MacroLine,MacroInclude>{
+	"\n" {
+		BEGIN(pop = INITIAL);
+		return Normal;
+	}
+	"\\\n" { return Macro; }
+	{ident} { return Macro; }
+}
+
+{ident} { return Ident; }
+
+"//"([^\n]|"\\\n")* |
+"/*"([^*]|"*"[^/])*"*"+"/" {
+	return Comment;
+}
+
+[LUu]?"'"/[^\\] {
+	BEGIN(CharLiteral);
+	yymore();
+}
+[LUu]?"'" {
+	BEGIN(CharLiteral);
+	return String;
+}
+([LU]|u8?)?"\""/[^\\%] {
+	BEGIN(StringLiteral);
+	yymore();
+}
+([LU]|u8?)?"\"" {
+	BEGIN(StringLiteral);
+	return String;
+}
+
+<CharLiteral,StringLiteral>{
+	"\\\n" |
+	"\\"[''""?\\abfnrtv] |
+	"\\"([0-7]{1,3}) |
+	"\\x"([[:xdigit:]]{2}) |
+	"\\u"([[:xdigit:]]{4}) |
+	"\\U"([[:xdigit:]]{8}) {
+		return Escape;
+	}
+}
+<StringLiteral>{
+	"%%" |
+	"%"[EO]?[ABCDFGHIMRSTUVWXYZabcdeghjmnprtuwxyz] |
+	"%"[ #+-0]*{width}?("."{width})?([Lhjltz]|hh|ll)?[AEFGXacdefginopsux] {
+		return Format;
+	}
+}
+
+<CharLiteral>{
+	[^\\'']*"'" {
+		BEGIN(pop);
+		return String;
+	}
+	[^\\'']+|. { return String; }
+}
+<StringLiteral>{
+	[^%\\""]*"\"" {
+		BEGIN(pop);
+		return String;
+	}
+	[^%\\""]+|. { return String; }
+}
+
+<MacroLine,MacroInclude>. {
+	return Macro;
+}
+
+.|\n { return Normal; }
+
+%{
+	(void)yyunput;
+	(void)input;
+%}
+
+%%
+
+const struct Lexer LexC = { yylex, &yyin, &yytext };
diff --git a/bin/dash/.gitignore b/bin/dash/.gitignore
new file mode 100644
index 00000000..63fccdc3
--- /dev/null
+++ b/bin/dash/.gitignore
@@ -0,0 +1,34 @@
+# .gitignore for dash
+
+# generated by autogen.sh
+/autom4te.cache/
+
+# generated by configure
+Makefile
+.deps
+.dirstamp
+/config.cache
+/config.h
+/config.log
+/config.status
+/stamp-h1
+
+# generated by make
+/src/token_vars.h
+
+# Apple debug symbol bundles
+*.dSYM/
+
+# backups and patch artefacts
+*~
+*.bak
+*.orig
+*.rej
+
+# OS generated files
+.DS_Store
+.DS_Store?
+._*
+.Spotlight*
+.Trash*
+*[Tt]humbs.db
diff --git a/bin/dash/COPYING b/bin/dash/COPYING
new file mode 100644
index 00000000..37f8189c
--- /dev/null
+++ b/bin/dash/COPYING
@@ -0,0 +1,56 @@
+Copyright (c) 1989-1994
+	The Regents of the University of California.  All rights reserved.
+Copyright (c) 1997 Christos Zoulas.  All rights reserved.
+Copyright (c) 1997-2005
+	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+
+This code is derived from software contributed to Berkeley by Kenneth Almquist.
+
+
+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.
+3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+
+mksignames.c:
+
+This file is not directly linked with dash.  However, its output is.
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU Bash, the Bourne Again SHell.
+
+Bash is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License with
+your Debian GNU/Linux system, in /usr/share/common-licenses/GPL, or with the
+Debian GNU/Linux hello source package as the file COPYING.  If not,
+write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+Boston, MA 02111 USA.
diff --git a/bin/dash/ChangeLog b/bin/dash/ChangeLog
new file mode 100644
index 00000000..406e20c0
--- /dev/null
+++ b/bin/dash/ChangeLog
@@ -0,0 +1,806 @@
+2014-11-17  Stéphane Aulery <saulery@free.fr>
+
+	* Correct typo in manual page.
+	* Document redirection file descriptor limitation.
+
+2014-10-30  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Catch variable length expansions on non-existant specials.
+
+2014-10-28  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Removed unnecessary pungetc on EOF from parser.
+	* Simplify EOF/newline handling in list parser.
+
+2014-10-27  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Add printf support for format string a, A, and F.
+	* Handle embedded NULs correctly in printf.
+	* Replace open-coded flushall in preadbuffer.
+	* Add likely tag in outmem.
+	* Add ifdefs around MEM_OUT handling in outmem.
+	* Remove unnecessary restoration of format string in printf.
+	* Remove getintmax in printf.
+	* Use error instead of warnx for fatal errors in printf.
+	* Optimise handling of backslash octals in printf.
+	* Simplify echo command.
+	* Handle -- in dotcmd.
+
+2014-10-13  Eric Blake <eblake@redhat.com>
+
+	* cd: support drive letters on Cygwin.
+
+2014-10-08  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Split unquoted $@/$* correctly when IFS is set but empty.
+	* Do not split quoted VSLENGTH and VSTRIM.
+	* Optimise nulonly away and just use quoted as before.
+
+2014-10-07  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Use setvareq to set OPTIND initially.
+
+2014-10-06  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Exit without arguments in a trap should use status outside traps.
+	* Do not allow break to break across function calls.
+	* Move common skipcount logic into skiploop.
+	* Allow return in loop conditional to set exit status.
+	* Return without arguments in a trap should use status outside traps.
+
+2014-10-03  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Do not clobber exitstatus in evalcommand.
+
+2014-10-02  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix use-after-free in dotrap/evalstring.
+	* Make sure evalskip is zero before running traps.
+	* Set exitstatus in onint.
+
+2014-09-29  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Kill pgetc_macro.
+	* Handle backslash newlines properly after dollar sign.
+	* Add nlprompt/nlnoprompt helpers.
+
+2014-09-28  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Correctly handle test ! ! = !.
+
+2014-09-26  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Small optimisation of command -pv change.
+	* Set command -p path to /usr/sbin:/usr/bin:/sbin:/bin.
+	* Change "characters" for printf precision to "bytes".
+	* Release 0.5.8.
+
+2014-09-26  Jonathan Nieder <jrnieder@gmail.com>
+
+	* Clarify "trap '' signals" syntax in manual page.
+
+2014-09-26  Adam Buchbinder <adam.buchbinder@gmail.com>
+
+	* Clarify that 0 and EXIT are both acceptable for exit traps.
+
+2014-09-26  Harald van Dijk <harald@gigawatt.nl>
+
+	* command: allow combining -p with -v.
+	* getjob: Fix off-by-one error for multiple of four job numbers
+
+2013-08-23  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Propagate EXP_QPAT in subevalvar.
+	* Initialise OPTIND after importing environment.
+	* Fixed argument parsing crash in test.
+
+2013-03-12  Peter Rosin <peda@lysator.liu.se>
+
+	* Add newline when tracing in poplocalvars.
+
+2013-01-10  Jérémie Courrèges-Anglas <jca+dash@wxcvbn.org>
+
+	* Markup fixes in manual for mandoc 1.12.1.
+
+2012-12-03  Harald van Dijk <harald@gigawatt.nl>
+
+	* Use PRIdMAX instead of %j in printf.
+
+2012-07-20  Kimo Rosenbaum <kimor79@yahoo.com>
+
+	* Fix typo for wait in manual.
+
+2012-06-09  Christoph Mathys <eraserix@gmail.com>
+
+	* Add support for ulimit -r.
+
+2012-03-11  Jim Meyering  <meyering@redhat.com>
+
+	* Avoid overflow for very long variable name.
+	$ perl -le 'print "v"x(2**31+1) ."=1"' | dash
+
+2012-02-25  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Sanitise environment variable names on entry.
+
+2011-08-17  David S. Miller <davem@davemloft.net>
+
+	* Allow building without LINEO support.
+	* Add top-level autogen.sh.
+
+2011-07-26  Harald van Dijk <harald@gigawatt.nl>
+
+	* Avoid imaxdiv when only one of the results is wanted.
+
+2010-07-09  maximilian attems <max@stro.at>
+
+	* Fix klibc DEBUG compilation.
+
+2011-07-09  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Merge SKIPFUNC/SKIPFILE and only clear SKIPFUNC when leaving dotcmd.
+
+2011-07-08  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Release 0.5.7.
+
+2011-07-07  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Optimize dash -c "command" to avoid a fork.
+	* Eliminate unnecessary promotion in echocmd.
+
+2011-05-25  Jim Meyering  <meyering@redhat.com>
+
+	* Avoid using undefined handler.
+
+2011-05-23  Jim Meyering  <meyering@redhat.com>
+
+	* Avoid gcc warning: variable 'oldstackp' set but not used.
+	* Avoid clang warning about dead store to "size".
+
+2011-05-22  Jonathan Nieder <jrnieder@gmail.com>
+
+	* Make outc an inline function.
+
+2011-05-02  Kalle Olavi Niemitalo <kon@iki.fi>
+
+	* Remove spurious space in descriptions of PS1, PS2, PS4.
+
+2011-04-10  Jonathan Nieder <jrnieder@gmail.com>
+ 
+	* Remove unused EV_BACKCMD flag.
+
+2011-03-15  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix clobbering of checkkwd.
+
+2011-03-15  Jonathan Nieder <jrnieder@gmail.com>
+
+	* Free IFS state after here document expansion.
+	* Use va_copy when reusing a va_list.
+
+2011-03-15  Harald van Dijk <harald@gigawatt.nl>
+
+	* Let funcnode refer to a function definition, not its first command.
+	* Improve LINENO support.
+
+2011-03-15  Brian Koropoff <bkoropoff@gmail.com>
+
+	* Port to Solaris.
+
+2011-03-11  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix backslash handling in read(1).
+
+2011-03-10  Jonathan Nieder <jrnieder@gmail.com>
+
+	* Dotcmd should exit with zero when doing nothing.
+
+2011-03-10  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix CTLESC clobbering by read(1).
+
+2011-03-10  Brian Koropoff <bkoropoff@gmail.com>
+
+	* Port to AIX.
+
+2011-03-10  Jilles Tjoelker <jilles@stack.nl>
+
+	* Replace GPL noclobberopen code with the FreeBSD version.
+	* Do not split the result of tilde expansion.
+
+2010-11-28  Maciej Żenczykowski <zenczykowski@gmail.com>
+
+	* Mark status as volatile in exitshell.
+
+2010-11-28  Jonathan Nieder <jrnieder@gmail.com>
+
+	* Use EXEXIT in place of EXEXEC.
+	* Stop documenting EXSHELLPROC.
+
+2010-11-28  Gerrit Pape <pape@smarden.org>
+
+	* Use exit status 127 when the script to run does not exist.
+
+2010-11-28  Philipp Weis <pweis@pweis.com>
+
+	* Document optional open parenthesis for case patterns.
+
+2010-11-28  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed trap/return regression due to SKIPEVAL removal.
+	* Allow the originator of EXERROR to set the exit status.
+	* Free IFS state in evalbackcmd.
+
+2010-10-18  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix ifsfirst/ifslastp leak in casematch.
+
+2010-10-07  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix EXEXEC status clobbering.
+
+2010-09-08  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix ifsfirst/ifslastp leak.
+	* Fix trailing field bug in read(1).
+
+2010-09-08  maximilian attems <max@stro.at>
+
+	* Debug compile fix.
+
+2010-09-08  Jilles Tjoelker <jilles@stack.nl>
+
+	* Fix varinit ordering that broke fc.
+
+2010-07-06  Gerrit Pape <pape@smarden.org>
+
+	* Check exit for eval NSUBSHELL.
+
+2010-07-06  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix loss of variables when hash collides.
+	* Removed dead code for eval NPIPE.
+
+2010-06-28  Gerrit Pape <pape@smarden.org>
+
+	* Don't clear eflag in evalbackcmd.
+
+2010-05-29  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Continue after EINTR in read(1) with no pending signals.
+
+2010-05-27  Jilles Tjoelker <jilles@stack.nl>
+
+	* Force fork if any trap is set, not just on EXIT.
+	* Fix corruption of redirections with byte 0x81.
+
+2010-05-27  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix poplocalvar on abnormal exit from function.
+	* Do not poplocalvars prematurely on regular utilities.
+	* Move null redirect checks into caller.
+	* Fix popredir on abnormal exit from built-in.
+	* Fix wait regression where it does not wait for all jobs.
+
+2010-05-26  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Replace cmdenviron with localvars.
+
+2010-05-25  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix poplocalvar leak.
+	* Move unsetvar functionality into setvareq.
+
+2010-05-24  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Add localvars nesting, local now fails outside functions.
+
+2010-05-03  Gerrit Pape <pape@smarden.org>
+
+	* Fix command -- crash.
+
+2010-04-15  H. Peter Anvin <hpa@zytor.com>
+
+	* Fix for job control off warning.
+
+2010-04-02  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Use faccessat if available.
+
+2010-04-02  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Make trap signal name/number errors non-fatal.
+	* Release 0.5.6.
+
+2010-04-02  maximilian attems <max@stro.at>
+
+	* Use TMPDIR in mkbuiltins.
+
+2010-03-10  Jilles Tjoelker <jilles@stack.nl>
+
+	* Fix logical or result value.
+
+2010-03-09  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix binary operator parsing.
+
+2009-11-26  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix off-by-one recordregion in readcmd.
+
+2009-09-28  Jim Meyering  <meyering@redhat.com>
+
+	don't read-uninitialized for \177 in a here-doc
+	A DEL (0177, dec 127) byte in a here-document would cause dash to
+	access uninitialized memory at the end of one of the syntax.c tables,
+	since those tables are sized to accommodate a maximum index of
+	BASESYNTAX + 126.  Make the generated tables one byte larger.
+	printf ':<<\\E\n\200y\nE'|./dash
+	* src/mksyntax.c (filltable): Use 258, not 257 as the size,
+	so that BASESYNTAX(=130) + 127 is a valid index.
+	(print): Likewise.
+	Don't emit explicit array dimension in declaration.
+
+2009-08-31  Eric Blake <ebb9@byu.net>
+
+	* Avoid compiler warnings on isdigit.
+
+2009-08-31  Matthew Burgess <matthew@linuxfromscratch.org>
+
+	* Add another missing LC_COLLATE to mkbuiltins.
+
+2009-08-31  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix NUL termination in readcmd.
+	* Lookup PWD after going through CDPATH.
+
+2009-08-11  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Pass EV_TESTED into evalcmd.
+	* Revert SKIPEVAL into EXEXIT.
+
+2009-08-11  Rocky Bernstein <rocky.bernstein@gmail.com>
+
+	* Add preliminary LINENO support.
+
+2009-08-11  Stefan Potyra <stefan.potyra@informatik.uni-erlangen.de>
+
+	* Honor tab as IFS whitespace when splitting fields in readcmd.
+
+2009-06-30  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Do not truncate file for FROMTO redirection.
+
+2009-06-27  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix quoted pattern patch breakage.
+
+2009-05-23  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix incorrect savefd conversions.
+
+2009-02-22  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix dowait signal race.
+	* Remove EXSIG.
+	* Do not close stderr when /dev/tty fails to open.
+	* Allow newlines after var name in for statements.
+	* Use CHKNL to parse case statements.
+
+2009-02-22  Gerrit Pape <pape@smarden.org>
+
+	* Update manual page to differentiate dash from ash.
+
+2009-01-14  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Add arith_yacc.h to dash_SOURCES.
+	* Release 0.5.5.1.
+
+2009-01-13  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Release 0.5.5.
+
+2009-01-13  Mark Mentovai <mmentovai@gmail.com>
+
+	* Fixed build on OS X.
+
+2008-12-26  Aleksey Cheusov <vle@gmx.net>
+
+	* Fixed build on NetBSD.
+
+2008-10-17  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Removed obsolete for loop syntax in manual.
+
+2008-08-05  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed getcwd build error for the non-glibc case.
+
+2008-06-13  Gerrit Pape <pape@smarden.org>
+
+	* Added missing right parenthesis in manual page.
+
+2008-06-13  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed 3,4-argument cases for test per POSIX.
+	* Made aexpr/oexpr non-recursive.
+	* Made t_lex reentrant.
+	* Made setinputfd static.
+	* Expand ENV before using it.
+	* Added support for -l.
+
+2008-05-19  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed non-leading slash treatment in expmeta.
+
+2008-05-07  Gerrit Pape <pape@smarden.org>
+
+	* Fixed lexical error in arithmetic expansion of & and |.
+
+2008-05-03  Dan McGee <dpmcgee@gmail.com>
+
+	* Fixed klibc/klcc build problems.
+	* Added gitignore.
+
+2008-05-03  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed _PATH_BSHELL warning.
+	* Test __GLIBC__ instead of _GNU_SOURCE.
+	* Restored warning when getcwd fails.
+	* Set default exvwarning2 arg0 for errors during early initialisation.
+	* Use uninitialized_var to silence bogus warnings.
+
+2008-05-02  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Restored non-glibc getcwd support.
+
+2008-03-07  Larry Doolittle <ldoolitt@recycle.lbl.gov>
+
+	* Fix cmdtxt crash on if statements.
+
+2008-01-01  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix slash treatment in expmeta.
+
+2007-12-27  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Add FAKEEOFMARK for expandstr.
+	* Do not show prompts in expandstr.
+
+2007-12-23  Gerrit Pape <pape@smarden.org>
+
+	* If imaxdiv() isn't available, use / and % operators.
+
+2007-12-23  Richard M Kreuter <kreuter@progn.net>
+
+	* Add set +o support.
+
+2007-12-23  Steve Langasek <steve.langasek@canonical.com>
+
+	* Fixed bad pointer arithmetic in evalcommand.
+
+2007-11-11  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Removed noexpand/length check on eofmark.
+	* Removed herefd hack.
+	* Expand here-documents in the current shell environment.
+
+2007-10-20  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Added configure --enable-glob and --enable-fnmatch options.
+	* Fix here-doc corruption.
+
+2007-10-17  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Replace shared illnum message by badnum function.
+
+2007-10-17  Oleg Verych <olecom@flower.upol.cz>
+
+	* Disallow completely blank strings in non-arithmetic context.
+
+2007-10-15  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed execing of scripts with no hash-bang.
+
+2007-10-11  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Add assignment support in arithmetic expansions.
+	* Size optimisations in arithmetic lexer.
+	* Add likely flags in expari.
+	* Use setvarint to set OPTIND.
+
+2007-10-08  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Report substition errors at expansion time.
+
+2007-10-06  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Add pushstackmark.
+	* Treat OPTIND=0 in the same way as OPTIND=1.
+	* Remove setvarsafe.
+	* Use intmax_t arithmetic in test.
+
+2007-10-05  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Made grabstackblock an inline wrapper for stalloc.
+
+2007-10-04  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix parsing of ${##1}.
+	* Size optimisations in parameter expansion parser.
+
+2007-10-04  Alexey Gladkov <legion@altlinux.org>
+
+	* Add --enable-static option to configure.
+
+2007-09-26  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Recognise here-doc delimiters terminated by EOF.
+
+2007-09-26  Roy Marples <uberlord@gentoo.org>
+
+	* Refresh stack pointers after makestrspace in _rmescapes.
+
+2007-09-25  Gerrit Pape <pape@smarden.org>
+
+	* Clarify description of -nt, -ot options to test builtin.
+	* Clarify syntax of the for command.
+
+2007-09-25  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Do not expand tilde in parameter expansion within quotes.
+	* Move parse-time quote flag detection to run-time.
+
+2007-09-24  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Do not quote back slashes in parameter expansions outside quotes.
+	* Perform tilde expansion in all parameter expansion words.
+	* Remove superfluous arinest test in CENDQUOTE.
+	* Remove superfluous arinest test for dqvarnest.
+	* Remove superfluous dblquote settings when ending arith.
+	* Remove arithmetic expansion collapsing at parse time.
+
+2007-09-22  Oleg Verych <olecom@flower.upol.cz>
+
+	* White space fixes for test(1).
+	* Use direct comparison instead of strcmp in test(1).
+
+2007-09-22  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Move flushall to the point just before _exit.
+
+2007-09-21  Denis Vlasenko <vda.linux@googlemail.com>
+
+	* Restore foreground process group on exit.
+
+2007-07-12  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Release 0.5.4.
+
+2007-05-12  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix redirect restore on closed file descriptors.
+	* Size optimisations in redir.c.
+
+2007-05-06  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Removed unnecessary inclusion of redir.h from parser.c.
+	* Invoke sh_error on error in copyfd.
+	* Use dup2 instead of copyfd in evalbackcmd.
+	* Replace copyfd by savefd and dup2.
+	* Removed redundant CLOEXEC calls.
+
+2007-05-05  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed typo in parser.h comment.
+
+2007-04-28  Dan Nicholson <dbn.lists@gmail.com>
+
+	* Set LC_COLLATE for sort in mkbuiltin.
+
+2006-10-22  Gerrit Pape <pape@smarden.org>
+
+	* Fixed command -v segmentation fault.
+
+2006-10-13  Alexey Gladkov <legion@altlinux.org>
+
+	* Check return code for getgroups and fwrite.
+
+2006-10-04  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed inverted char class matching.
+
+2006-05-23  Alexey Gladkov <legion@altlinux.org>
+
+	* Added --with-libedit option to configure.
+
+2006-03-29  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Removed useless parsebackquote flag.
+	* Use alloca to get rid of setjmp in parse.c.
+	* Only use signed char for syntax arrays.
+
+2006-01-12  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed eval exit status with empty arguments.
+
+2005-11-26  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Release 0.5.3.
+
+2005-11-14  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fix \c spillage across echo commands.
+
+2005-11-13  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Remove unnecessary truncation in _STPUTC.
+	* Always call conv_escape_str in echocmd.
+
+2005-11-04  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Use mktemp if tempfile is not available.
+
+2005-10-30  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed support for disabling job control.
+
+2005-10-29  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Updated BSD licence to 3-clause version per NetBSD.
+	* Updated copyright.
+	* Removed CVS IDs and inclusion of sys/cdefs.h.
+	* Removed use of __P from error.h.
+	* Use bsd_signal if it exists and signal does not.
+	* Stop using sysexits.h in commandcmd.
+	* Use stat if stat64 does not exist.
+	* Added default implementation of bsearch.
+	* Added getpwhome as a wrapper for getpwnam.
+	* Fixed gcc 4.0 compilation problems.
+	* Added missing system.h inclusion for mempcpy.
+	* Added default implementation of strsignal.
+	* Added default implementation of killpg.
+	* Disable ulimit if there is no getrlimit.
+	* Disable histcmd completely when SMALL is defined.
+	* Added default definition for SSIZE_MAX.
+	* Removed standalone/csh support from printf.
+	* Added dummy strtod implementation.
+	* Removed standalone/csh support from test.
+	* Added dummy sysconf implementation.
+	* Include system.h for stpcpy in nodes.c.
+	* Added out-of-line ctypes functions for klibc.
+	* Fixed fallback stpcpy implementation.
+
+2005-10-26  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Size optimisations in preadbuffer().
+
+2005-10-01  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Skip NUL characters properly in input.c.
+
+2005-03-28  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Removed some unnecessary inclusions of input.h.
+	* Removed unnecessary inclusion of main.h from eval.c.
+	* Removed unnecessary inclusion of eval.h from parser.c.
+	* Generalise setinputfile for use in read_profile/readcmdfile.
+	* Handle SKIPEVAL in read_profile by exiting.
+	* Let evaltree handle traps from cmdloop.
+	* Reset evalskip after minusc is executed.
+	* Stop executing traps once SKIPEVAL is seen.
+	* Only handle each signal once in dotrap.
+
+2005-03-25  Gerrit Pape <pape@smarden.org>
+
+	* Add trailing equal sign in setvar for variables set to null.
+
+2005-03-25  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Cleaned up src/Makefile.am.
+	* Get rid of duplicate -g -O2 in CFLAGS.
+	* Eliminate first null termination in setvar.
+	* Turn evalskip into a bit field.
+
+2005-03-25  Gilles Chanteperdrix <gilles.chanteperdrix@laposte.net>
+
+	* Fixed support for cross-compilation.
+
+2005-03-03  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Removed qflag.
+	* Removed redundant setstackmark from dotcmd.
+	* Do not clobber exit status in dotcmd.
+
+2005-03-02  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Renamed symbols to avoid conflict with libc.
+	* Optimisations in bltin/test.c.
+
+2005-02-28  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Replaced EXEVAL with SKIPEVAL.
+	* Update funcnest atomically.
+	* Only set skipcount for break and continue.
+	* Removed expcmd built-in.
+	* Normalise input in likely/unlikely macros.
+
+2005-02-28  A Costa <agcosta@gis.net>
+
+	* Corrected that/than typo in manual page.
+
+2005-02-25  A Costa <agcosta@gis.net>
+
+	* Corrected grammar in manual page.
+
+2005-02-25  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Changed boolean rootshell into shlvl counter.
+	* Catch set -e exits within built-in commands.
+	* Size optimisations with setjmp in main().
+	* Only reread exitstatus on EXEXIT in exitshell.
+	* Eliminated global exerrno.
+
+2005-01-31  Gerrit Pape <pape@smarden.org>
+
+	* Release 0.5.2.
+	* Corrected manual entry about ENV and non-interactive shells.
+
+2004-11-24  Gerrit Pape <pape@smarden.org>
+
+	* Spell behaviour consistently in manual page.
+
+2004-11-23  A Costa <agcosta@gis.net>
+
+	* Fixed spelling errors in manual page.
+
+2004-08-21  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Size optimisations around varvalue() in src/expand.c.
+	* Fixed signed char promotion in src/expand.c.
+
+2004-08-18  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed $@ expansion when leading argument is null in src/expand.c.
+
+2004-08-07  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Allow negative pid argument to kill(1) in src/jobs.c.
+
+2004-08-04  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed cd - when OLDPWD is unset in src/cd.c.
+
+2004-07-09  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Include system.h (Gerrit Pape):
+	  . src/mystring.c
+	  . src/var.c
+	  . src/bltin/printf.c
+
+2004-07-03  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Release 0.5.1.
+	* Use automake and autoconf.
+	* Include stdlib.h for exit(3) in src/mksyntax.c.
+
+2004-06-29  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Added sigclearmask.
+	* Removed hack for _setjmp/_longjmp.
+	* Added default implementations of mempcpy/stpcpy/strchrnul.
+	* Use strtoll/strtoull if strtoimax/strtoumax are unavailable.
+	* Removed sh.1 to dash.1.
+
+2004-05-28  Herbert Xu <herbert@gondor.apana.org.au>
+
+	* Fixed vstype trim operator ordering in cmdputs.
+	* Fixed quote for CTLENDVAR in cmdputs.
+	* Fixed VSLENGTH crash in cmdputs.
+	* Turned vstype back into a 2-d array of chars.
+	* Added POSIX character class support in pmatch.
+
+For older ChangeLogs see ChangeLog.O.
+
+ChangeLog ends here
diff --git a/bin/dash/ChangeLog.O b/bin/dash/ChangeLog.O
new file mode 100644
index 00000000..dfdb2cec
--- /dev/null
+++ b/bin/dash/ChangeLog.O
@@ -0,0 +1,1023 @@
+dash (0.4.26) unstable; urgency=low
+
+  * Disabled fnmatch code again (closes: #240887).
+  * Updated copyright.
+  * Updated German debconf translation (Florian Ernst, closes: #244507).
+  * Fixed obstack corruption in setprompt (closes: #246635).
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 30 Apr 2004 21:48:52 +1000
+
+dash (0.4.25) unstable; urgency=low
+
+  * Fixed use-after-free bug in setvareq (Vladimir N. Oleynik).
+  * Fixed value of expdest after _STPUTC in expandarg (closes: #238265).
+
+ -- Herbert Xu <herbert@debian.org>  Thu, 18 Mar 2004 20:55:57 +1100
+
+dash (0.4.24) unstable; urgency=low
+
+  * Fixed segmentation fault when PWD is undefined.
+
+ -- Herbert Xu <herbert@debian.org>  Tue,  9 Mar 2004 19:58:41 +1100
+
+dash (0.4.23) unstable; urgency=low
+
+  * Verify PWD before using it.
+
+ -- Herbert Xu <herbert@debian.org>  Mon,  8 Mar 2004 20:12:27 +1100
+
+dash (0.4.22) unstable; urgency=low
+
+  * Read PWD from environment (closes: #228659).
+  * Added Danish debconf translation (Claus Hindsgaul, closes: #233756).
+  * Added check_gcc to support gcc 2.95 (closes: #235933).
+  * Perform here-doc expansion on PS1/PS2/PS4 (closes: #230858).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  7 Mar 2004 21:50:04 +1100
+
+dash (0.4.21) unstable; urgency=low
+
+  * Fixed typo that broke ulimit (GCS, closes: #228369).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 19 Jan 2004 19:02:32 +1100
+
+dash (0.4.20) unstable; urgency=low
+
+  * Added Dutch debconf translation (Tim Dijkstra, closes: #218904).
+  * Check existence RLIMIT symbols for ulimit.
+  * Removed table lookup in errmsg.
+  * Restored NULL check in cmdtxt.
+  * Restored ash postrm to purge debconf entries (closes: #221913).
+  * Fixed exit status of exit in EXIT trap (closes: #227734).
+  * Updated Brazilian debconf translation (Andre Luis Lopes, closes: #228095).
+  * Restored goodname check in prehash.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 17 Jan 2004 09:57:14 +1100
+
+dash (0.4.19) unstable; urgency=low
+
+  * Fixed handling of evalskip in dotcmd (closes: #212975).
+  * Updated Russian debconf translation (Ilgiz Kalmetev, closes: #214333).
+  * Added Portugese debconf translation (Bruno Rodrigues, closes: #216214).
+  * Updated Spanish debconf translation (Carlos Valdivia, closes: #216338).
+  * Fixed length expansion of special variables (closes: #216767).
+  * Replaced umask builtin with pdksh version.
+  * Reverted bogus eval change in 0.3.1-20.
+  * Added vmemory/locks support in ulimit.
+  * Call install -D instead of cp for merged template.
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 29 Oct 2003 22:14:22 +1100
+
+dash (0.4.18) unstable; urgency=low
+
+  * Fixed boundary checks in getopts.
+  * Updated Japanese debconf template (Tomohiro KUBOTA, closes: #192382).
+  * Use -falign-* instead -malign-*.
+  * Use strtoll for parsing integers in arith expansion.
+  * Added support for add-shell/remove-shell (closes: #163131).
+  * Fixed JOBS ifdefs in sprint_status (closes: #211009).
+  * Fixed bit-wise or in arith expansion (Mototoshi KONDO, closes: #212825).
+  * Print PS4 on previous stderr.
+  * Converted debconf templates to gettext (Christian Perrier,
+    closes: #200112).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 27 Sep 2003 14:26:36 +1000
+
+dash (0.4.17) unstable; urgency=low
+
+  * Reset rehash when recylcing cmd entries.
+  * Fixed null arg0 segfault with -c (closes: #191687).
+  * Relocate job pointers in makejob (closes: #191595).
+
+ -- Herbert Xu <herbert@debian.org>  Sat,  3 May 2003 20:57:46 +1000
+
+dash (0.4.16) unstable; urgency=low
+
+  * Fixed printf so that exit status is cleared on entry.
+  * Call nextopt() in printf.
+  * Fixed command substitution corruption by grabbing expdest in expbackq
+    (closes: #187896).
+
+ -- Herbert Xu <herbert@debian.org>  Mon,  7 Apr 2003 21:21:30 +1000
+
+dash (0.4.15) unstable; urgency=low
+
+  * Fixed octal escapes in echo/printf (closes: #187827).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  6 Apr 2003 20:45:38 +1000
+
+dash (0.4.14) unstable; urgency=low
+
+  * Added missing newline when printing in dowait.
+  * Do not print status in dowait when stopped.
+  * Fixed job status display.
+  * Fixed current job setting.
+  * Fixed kill segfault with no arguments (closes: #187189).
+  * Fixed sorting of set output.
+  * Removed setvar builtin.
+
+ -- Herbert Xu <herbert@debian.org>  Thu,  3 Apr 2003 20:38:33 +1000
+
+dash (0.4.13) unstable; urgency=low
+
+  * Fixed precision type on 64 bit systems in showvars.
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 26 Mar 2003 20:00:03 +1100
+
+dash (0.4.12) unstable; urgency=low
+
+  * Fixed dash_errno build problem with gcc 3.2.
+
+ -- Herbert Xu <herbert@debian.org>  Tue, 25 Mar 2003 22:28:50 +1100
+
+dash (0.4.11) unstable; urgency=low
+
+  * Removed unused pgrp field from job structure.
+  * Free jobs when calling wait with no arguments.
+  * Fixed build problem with bison.
+  * Merged changes from NetBSD 20030123.
+   . printf:
+    - Fixed mklong sefault.
+    - Fixed precision/field width with %b.
+   . Improved option parsing of command(1).
+   . Added rudimentary support for PS4.
+  * Moved builtin flags into builtins.def.
+  * Updated Spanish debconf template (Carlos Valdivia Yagüe, closes: #178359).
+  * Fixed ordering of redirection versus assignment substitution.
+  * Fixed potential setvareq memory leaks.
+  * Use bison instead of byacc.
+  * Fixed wait(1) race condition.
+  * Fixed alignment memory corruption bug in growstackblock().
+  * Fixed potential memory corruption in parsing position parameters.
+  * Fixed getopts done check.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 24 Mar 2003 20:42:29 +1100
+
+dash (0.4.10) unstable; urgency=low
+
+  * Fixed redirection fd leak when execing.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 19 Jan 2003 13:25:41 +1100
+
+dash (0.4.9) unstable; urgency=low
+
+  * Reset exitstatus in evalsubshell if backgnd is true.
+  * Fixed glibc glob syntax error in expand.c.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 11 Jan 2003 16:04:02 +1100
+
+dash (0.4.8) unstable; urgency=low
+
+  * Removed backgnd flag from ncmd due to previous redirection change.
+  * Set lim after the stack stablises in updatepwd (closes: #173884).
+  * Do not clobber the exitstatus after redirection.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 23 Dec 2002 19:50:06 +1100
+
+dash (0.4.7) unstable; urgency=low
+
+  * Merged clearredir with reset code in redir.c.
+  * Redirect before command search in evalcommand (closes: #168862).
+  * Build binary-all packages in binary-indep (closes: #173191).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 21 Dec 2002 13:52:37 +1100
+
+dash (0.4.6) unstable; urgency=low
+
+  * Restored code for leaving job control.
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  8 Dec 2002 15:21:58 +1100
+
+dash (0.4.5) unstable; urgency=low
+
+  * Optimised doformat so that vsnprintf is usually called only once.
+  * Reset redirlist in clearredir so that popredir can work (closes: #170247).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 23 Nov 2002 22:09:59 +1100
+
+dash (0.4.4) unstable; urgency=low
+
+  * Fixed duplicate define warnings in init.c.
+  * Set debhelper compat to 4.
+  * Vanishing mail boxes no longer elicit "you have mail" messages.
+  * Function redirection errors no longer abort the shell.
+  * Fixed potential memory leak in redirect.
+  * Only allocate memory if necessary in redirect.
+  * Reap dead here documents.
+  * Do not strdup default values of static shell variables.
+  * Removed unnecessary setprompt(0) calls.
+  * Read in BUFSIZ chunks rather than BUFSIZ - 1.
+  * Documented undefined escape behaviour for echo(1) (closes: #167893).
+  * Do va_copy when we use a va_list twice (closes: #169503).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 20 Nov 2002 19:48:31 +1100
+
+dash (0.4.3) unstable; urgency=low
+
+  * Added manual entry for PPID.
+  * Exporting an unset variable no longer causes it to be set.
+  * Fixed fd0 redirection in asynchronous lists.
+  * Only stat if necessary in cdcmd (see #42880).
+  * Removed extra newline in error message in arith lexer.
+  * Set heredoclist to 0 ASAP in parseheredoc.
+  * Removed BSD advertising clause from copyright file.
+  * Check non-ash diversions as well in dash.postinst.
+  * Duplicated diversion checking in ash.postinst (closes: #166441).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 26 Oct 2002 21:28:33 +1000
+
+dash (0.4.2) unstable; urgency=low
+
+  * Give benefits of dash in templates (closes: #161527).
+  * Fixed signed/unsigned on result of xwrite (closes: #161606).
+  * Removed support for SIG prefixes in kill and trap.
+  * Added -- processing in trap.
+  * Dropped use of unset in postinst (closes: 161868).
+  * Fixed printf(1) %* processing on bad integers and zero.
+  * Use stat64 in test(1).
+  * Allocate group_array with stalloc in test(1).
+  * Disabled alias checking after a pattern in a case statement.
+  * Wait now returns 128 + last trapped signal.
+  * Printf now keeps going after errors.
+  * Empty non-trivial parameter expansions are now removed correctly.
+  * Call reset() before exitshell() is called.  This fixes the bug where
+    returning an error from a function running under set -e caused the exit
+    trap to be taken with evalskip set.
+  * Fixed quoting of empty strings in single_quote().
+  * Show line numbers on all errors.
+  * Function names must be valid identifiers.
+  * Removed unused dependency on groff.
+  * Fixed race condition before entering a function.
+  * Fixed getopts initialisation for functions.
+  * Added memory barriers in INT macros.
+  * Banned empty compound lists in most places.
+  * Keep usage counters on functions (closes: #164234).
+  * Updated copyright file.
+  * Check evalskip in evalstring (closes: #165056).
+  * Merged changes from NetBSD 1.6:
+   . Added intmax support in printf(1).
+   . Implemented set -u.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 19 Oct 2002 14:23:11 +1000
+
+dash (0.4.1) unstable; urgency=low
+
+  * Removed extra new line in command -v output for aliases.
+  * Removed alais prefix in the output of alias.
+  * Recognise octal and hex numbers in arith expansion (closes: #151449).
+  * Added sh(1) entries for echo, printf and test (closes: #156446).
+  * Renamed to dash --- the Debian Almquist Shell.
+  * Cleaned up rules file (Matej Vela).
+  * Check mtime instead of size in chkmail per POSIX.
+  * Added support for LFS (closes: #157884).
+  * Added SuS options to cd and pwd (closes: #145828).
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 13 Sep 2002 20:35:06 +1000
+
+ash (0.3.8-38) unstable; urgency=low
+
+  * Turned pre-dependency to dependency in udeb since the former is not allowed
+    (closes: #143749).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 28 Apr 2002 11:59:05 +1000
+
+ash (0.3.8-37) unstable; urgency=low
+
+  * Added Japanese debconf translation (Tomohiro KUBOTA, closes: #137431).
+  * Added missing escapes in manual page (Aaron Schrab, closes: #137966).
+  * Added Russian debconf translation (Ilgiz Kalmetev, closes: #137618).
+  * Fixed trap(1) documentation (closes: #140973).
+  * Do not abort if getcwd fails.
+
+ -- Herbert Xu <herbert@debian.org>  Wed,  3 Apr 2002 20:58:09 +1000
+
+ash (0.3.8-36) unstable; urgency=low
+
+  * Added library dependency for ash-udeb.
+  * Handle null case statements correctly.
+  * Fixed alias expansions in case statements (NetBSD).
+  * Disabled unused jobid command.
+  * Corrected documentation about shifting too much.
+  * Added French debconf translation (Denis Barbier, closes: #134625).
+  * Updated Spanish debconf translation (Carlos Valdivia, closes: #136366).
+
+ -- Herbert Xu <herbert@debian.org>  Sat,  2 Mar 2002 18:31:22 +1100
+
+ash (0.3.8-35) unstable; urgency=low
+
+  * Moved PWD initialisation into var.c (closes: #124032).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 24 Dec 2001 09:34:55 +1100
+
+ash (0.3.8-34) unstable; urgency=low
+
+  * NSEMI must be NOR + 1.
+  * Set exitstatus to zero before evaluating cases (closes: #124066).
+  * Explicitly set default answer of the ash/sh question to false so that
+    people whose debconf priority is set to low and who keeps banging on their
+    keyboards don't accidently end up with ash as /bin/sh.
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 21 Dec 2001 20:30:49 +1100
+
+ash (0.3.8-33) unstable; urgency=low
+
+  * Added missing inclusion of bltin.h in bltin/times.c.
+
+ -- Herbert Xu <herbert@debian.org>  Thu, 13 Dec 2001 18:46:07 +1100
+
+ash (0.3.8-32) unstable; urgency=low
+
+  * Back slashes in expansions are now escaped (closes: #121516).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 28 Nov 2001 20:15:01 +1100
+
+ash (0.3.8-31) unstable; urgency=low
+
+  * Made sure all back slashes are escaped.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 26 Nov 2001 19:10:27 +1100
+
+ash (0.3.8-30) unstable; urgency=low
+
+  * Restored fnmatch(3) code.
+  * Treat escaped slashes correctly while globbing.
+  * Restored missing EV_EXIT check in evalcommand (closes: #120364).
+  * Fixed stack corruption in _rmescapes.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 25 Nov 2001 17:51:19 +1100
+
+ash (0.3.8-29) unstable; urgency=low
+
+  * Added missing va_end in fmtstr (NetBSD).
+  * Removed shellproc crap.
+  * Updated Swedish debconf translation (Mikael Hedin, closes: #116097).
+  * Updated German debconf translation (Andreas Metzler, closes: #117160).
+  * Break now treats illegal numbers according to SuS.
+  * Errors in special builtins now rise to the top.
+  * Normal redirection errors no longer abort the shell.
+  * Functions now have the same variable assignment properties as special
+    builtins.
+
+ -- Herbert Xu <herbert@debian.org>  Sat,  3 Nov 2001 11:36:36 +1100
+
+ash (0.3.8-28) unstable; urgency=low
+
+  * Local variables are now unset properly in shprocvar() (closes: #114917).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 13 Oct 2001 14:07:21 +1000
+
+ash (0.3.8-27) unstable; urgency=low
+
+  * Kill no longer aborts if it fails to kill someone.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 30 Sep 2001 22:20:36 +1000
+
+ash (0.3.8-26) unstable; urgency=low
+
+  * The sh.1.gz diversion now agrees with reality (closes: #113831).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 29 Sep 2001 08:43:27 +1000
+
+ash (0.3.8-25) unstable; urgency=low
+
+  * Only read ENV if the shell is interactive (closes: #110421).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 29 Aug 2001 19:18:53 +1000
+
+ash (0.3.8-24) unstable; urgency=low
+
+  * Handle SIGINT when waiting even if there is no trap (closes: #107699).
+  * Protect all makejob/forkshell/waitforjobs sequences from SIGINT.
+  * Work around gcc bug that generates bad ..ng references (closes: #107994).
+
+ -- Herbert Xu <herbert@debian.org>  Wed,  8 Aug 2001 20:28:28 +1000
+
+ash (0.3.8-23) unstable; urgency=low
+
+  * Fixed fence post error in scanleft (closes: #107229).
+  * Removed stunalloc in expname as it interferes with addfname.
+  * Fixed CTLESC skipping in scanright.
+
+ -- Herbert Xu <herbert@debian.org>  Thu,  2 Aug 2001 20:06:00 +1000
+
+ash (0.3.8-22) unstable; urgency=low
+
+  * Fixed trailing back slash bug in echo/printf (closes: #106693).
+  * Some quoted's are meant to be quotes.
+  * Added Brazilian translation (Andre Luis Lopes, closes: #107041).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 30 Jul 2001 20:21:52 +1000
+
+ash (0.3.8-21) unstable; urgency=low
+
+  * Fixed EV_EXIT/redirection bugs that caused core dumps.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 28 Jul 2001 17:03:28 +1000
+
+ash (0.3.8-20) unstable; urgency=low
+
+  * Don't save fd2 if job control is turned off.
+  * Don't push redirections when EV_EXIT is set.
+  * Fixed assignment recognition in the presence of back ticks.
+  * Combined checkkwd and checkalias.
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 27 Jul 2001 22:29:41 +1000
+
+ash (0.3.8-19) unstable; urgency=low
+
+  * Recompute strings after growing in subevalvar (closes: #106050).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 23 Jul 2001 21:16:50 +1000
+
+ash (0.3.8-18) unstable; urgency=low
+
+  * Added more space optimisations for udeb on i386.
+  * Set stack mark in patmatch (closes: #106050).
+  * Fixed theoretical bug in expari.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 21 Jul 2001 20:08:15 +1000
+
+ash (0.3.8-17) unstable; urgency=low
+
+  * Don't complain about unknown escape codes in echo and printf
+    (closes: #105659).
+  * Updated build-time dependency on groff-base (closes: #105612).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 18 Jul 2001 19:33:20 +1000
+
+ash (0.3.8-16) unstable; urgency=low
+
+  * Fixed backslash bug in new pattern matching code.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 16 Jul 2001 21:47:39 +1000
+
+ash (0.3.8-15) unstable; urgency=low
+
+  * Added Swedish translation of templates (Martin Sjögren, closes: #103158).
+  * Restored escape code support in echo.
+  * Removed assignment builtins since it is at best undefined by the SuS and
+    also can't be implemented consistently.
+  * Removed extraneous volatile modifier (closes: #104518).
+  * General overhaul of word expansion (closes: #96588).
+  * Redirection prefixes no longer stop assignments from being recognised.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 15 Jul 2001 17:27:03 +1000
+
+ash (0.3.8-14) unstable; urgency=low
+
+  * Divert sh.1.gz to sh.distrib.1.gz (closes: #102251).
+  * Added HETIO support for ^D and ^U (Aaron Lehmann, closes: #102215).
+  * Added Spaniash translation of debconf templates (Carlos Valdivia Yagüe,
+    closes: #103040).
+  * Added versioned build-time dependency on groff.
+
+ -- Herbert Xu <herbert@debian.org>  Mon,  2 Jul 2001 19:32:03 +1000
+
+ash (0.3.8-13) unstable; urgency=low
+
+  * Fixed a bug where errors in pipelines which are part of andor lists were
+    not ignored when -e is in effect.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 25 Jun 2001 19:40:27 +1000
+
+ash (0.3.8-12) unstable; urgency=low
+
+  * Rewrote arith_lex.l in C (Aaron Lehmann, closes: #101741).
+  * && and || in arithmetic expansions now return either 0 or 1.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 24 Jun 2001 20:14:29 +1000
+
+ash (0.3.8-11) unstable; urgency=low
+
+  * Check for NULL argument in evaltree() (closes: #98865, #98867).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 27 May 2001 17:53:14 +1000
+
+ash (0.3.8-10) unstable; urgency=low
+
+  * Use /bin/ash in postinst to sidestep bugs in other shells (closes: #98739).
+  * Exit status is now tested on non-negated pipelines (closes: #98736).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 26 May 2001 23:56:07 +1000
+
+ash (0.3.8-9) unstable; urgency=medium
+
+  * IFS is now fetched using bltinlookup() again in read (closes: #98343).
+  * Divert sh(1) man page as well as /bin/sh (closes: #98525).
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 25 May 2001 20:30:06 +1000
+
+ash (0.3.8-8) unstable; urgency=low
+
+  * Fixed diversion removal in prerm (duh, closes: #98031).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 21 May 2001 20:52:48 +1000
+
+ash (0.3.8-7) unstable; urgency=low
+
+  * Fixed diversion test in prerm (closes: #98031).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 20 May 2001 12:30:53 +1000
+
+ash (0.3.8-6) unstable; urgency=low
+
+  * Make sure that fd2 is closed when clearing redirects (closes: #96619).
+  * Fixed memory corruption in stunalloc().
+  * The output of export/readonly/set is now correctly quoted.
+  * Fixed newline eating bug in expbackq().
+  * Set OLDPWD.
+  * Removed ash-medium as neither bf or di uses it.
+  * Wait now waits for all its argument rather than the first one.
+  * Wait will exit with 129 when interrupted by a signal for a which a trap has
+    been set.
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 18 May 2001 21:51:41 +1000
+
+ash (0.3.8-5) unstable; urgency=low
+
+  * Added German translation to template file (Sebastian Feltel,
+    closes: #96203).
+  * Added missing initialisation in setalias() (closes: #95433).
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  4 May 2001 20:54:31 +1000
+
+ash (0.3.8-4) unstable; urgency=low
+
+  * Disabled fnmatch code as fnmatch(3) in glibc is broken.
+  * Fixed echo example in man page (Kalle Olavi Niemitalo, closes: #96014).
+  * Fixed trailing semicolon bug with eval (NetBSD).
+  * Fixed globbing inconsistency with broken symlinks (NetBSD).
+
+ -- Herbert Xu <herbert@debian.org>  Wed,  2 May 2001 22:57:16 +1000
+
+ash (0.3.8-3) unstable; urgency=low
+
+  * Work around broken autoconf scripts (closes: #95430).
+
+ -- Herbert Xu <herbert@debian.org>  Tue,  1 May 2001 18:27:50 +1000
+
+ash (0.3.8-2) unstable; urgency=low
+
+  * Save checkalias before calling xxreadtoken() (closes: #95628).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 29 Apr 2001 17:36:01 +1000
+
+ash (0.3.8-1) unstable; urgency=low
+
+  * NetBSD-current version as of 20010316.
+  * Removed code that sets IFS.
+  * Fixed memory leak with PWD.
+  * Set PPID.
+  * Fixed inconsistencies in alias expansion.
+  * Restored original output code.
+  * Enabled fnmatch code again.
+  * Added builtin printf.
+  * Offer to divert /bin/sh (closes: #70462).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 25 Apr 2001 22:32:39 +1000
+
+ash (0.3.7-16) unstable; urgency=low
+
+  * Fixed incorrect default IFS in readcmd (closes: #88950).
+  * Added missing return in hashcmd.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  9 Mar 2001 20:44:40 +1100
+
+ash (0.3.7-15) unstable; urgency=low
+
+  * Unknown escape codes are now prnted literally by echo (closes: #82869).
+  * Made hetio_read_input() fail if fd is not stdin.
+  * Some uses of VSQUOTE were really meant to be quotes (closes: #88777).
+  * Build different ashes in different subdirectories.
+
+ -- Herbert Xu <herbert@debian.org>  Thu,  8 Mar 2001 21:32:28 +1100
+ 
+ash (0.3.7-14) unstable; urgency=low
+
+  * Removed predependency from udeb (closes: #81995).
+  * Added /bin/sh symlink to udeb (closes: #81967).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 13 Jan 2001 15:23:21 +1100
+
+ash (0.3.7-13) unstable; urgency=low
+
+  * Renamed the udeb to ash-udeb.
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 20 Dec 2000 19:32:34 +1100
+
+ash (0.3.7-12) unstable; urgency=low
+
+  * Added support for udebs (Randolph Chung, closes: #79237).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 16 Dec 2000 13:53:28 +1100
+
+ash (0.3.7-11) unstable; urgency=low
+
+  * Preserve the previous exit status upon entering a function
+    (closes: #78374).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  3 Dec 2000 13:34:27 +1100
+
+ash (0.3.7-10) unstable; urgency=low
+
+  * Merged changes for GNU from Igor Khavkine.
+  * Minimise the number of sigactions.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  3 Nov 2000 20:31:52 +1100
+
+ash (0.3.7-9) unstable; urgency=low
+
+  * Predepend on the libraries.
+  * Always save fd 2 when it is redirected (closes: #75302).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 22 Oct 2000 08:40:40 +1100
+
+ash (0.3.7-8) unstable; urgency=high
+
+  * More redirection fixes (closes: #73613).
+
+ -- Herbert Xu <herbert@debian.org>  Thu,  5 Oct 2000 18:22:17 +1100
+
+ash (0.3.7-7) unstable; urgency=high
+
+  * Added missing break in redirection code (closes: #72956).
+
+ -- Herbert Xu <herbert@debian.org>  Tue,  3 Oct 2000 07:58:04 +1100
+
+ash (0.3.7-6) unstable; urgency=low
+
+  * command -[vV] no longer displays an error message on stdout.
+  * Redirecting to /proc/self/fd/* now works (closes: #72852).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  1 Oct 2000 12:56:39 +1100
+
+ash (0.3.7-5) unstable; urgency=low
+
+  * Implemented set -a.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 30 Sep 2000 16:00:33 +1100
+
+ash (0.3.7-4) unstable; urgency=low
+
+  * Added build-time dependency on debhelper (closes: #69920).
+  * Extended maximum length of arithmetic expansions to match 32-bit integers.
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 20 Sep 2000 14:28:16 +1100
+
+ash (0.3.7-3) unstable; urgency=low
+
+  * Switch to the old globbing code since glob(3) is hopelessly broken
+    (closes: #69455).
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 21 Aug 2000 20:37:15 +1000
+
+ash (0.3.7-2) unstable; urgency=low
+
+  * Call glob(3) with GLOB_NOMAGIC (ouch).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  6 Aug 2000 17:47:08 +1000
+
+ash (0.3.7-1) unstable; urgency=low
+
+  * NetBSD-current version as of 20000729.
+  * Use fnmatch(3) and glob(3).
+  * Fixed the use of backslashes in the pattern in parameter substitutions,
+    hopefully for the last time.
+  * Applied HETIO patch and built ash.medium (closes: #50788).  Will do ash.big
+    when readline is fixed so that it doesn't leak anymore.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  4 Aug 2000 21:36:44 +1000
+
+ash (0.3.6-5) unstable; urgency=low
+
+  * Fixed manpage entry for read with patch from Kevin Ryde (closes: #62500).
+  * Fixed a file descriptor leak for pipelines.
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 19 Apr 2000 18:56:20 +1000
+
+ash (0.3.6-4) unstable; urgency=low
+
+  * Fixed the case of an empty command with redirections.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  7 Apr 2000 12:07:18 +1000
+
+ash (0.3.6-3) unstable; urgency=low
+
+  * ! is now recognised correctly.
+  * Ash is now more strict on the syntax, e.g., a lone ! is no longer accepted
+    as an alternative to ! true.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  7 Apr 2000 10:46:06 +1000
+
+ash (0.3.6-2) unstable; urgency=low
+
+  * Fixed a problem with fmtstr() which broke getopts.
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  2 Apr 2000 10:49:26 +1000
+
+ash (0.3.6-1) unstable; urgency=low
+
+  * NetBSD-current version as of 20000326.
+  * Added a Build-Depends on groff (closes: #61041).
+  * Implemented noclobber (closes: #59028).
+  * Rewrote output.c to use stream IO.
+
+ -- Herbert Xu <herbert@debian.org>  Sat,  1 Apr 2000 19:24:31 +1000
+
+ash (0.3.5-10) frozen unstable; urgency=low
+
+  * Don't stat mail boxes in non-interactive mode (closes: #59213).
+  * Added an fflush(stdout) to the times builtin (closes: #59027).
+  * Documented the times builtin.
+  * Added source depends.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 18 Mar 2000 18:58:44 +1100
+
+ash (0.3.5-9) unstable; urgency=low
+
+  * Double quotes inside paramater substitutions inside double quotes are now
+    ignored as in bash (the originial behaviour was POSIX compliant too but
+    IMHO this one makes a little bit more sense).
+    This one broke mwm (but it was actually mwm's fault).
+  * Corrected backslash/CTLESC treatment for patterns in parameter
+    substitutions.
+
+ -- Herbert Xu <herbert@debian.org>  Sat,  6 Nov 1999 18:13:19 +1100
+
+ash (0.3.5-8) unstable; urgency=low
+
+  * Replaced use of echo -n in manual page with escape codes.
+  * Made FHS compliant (closes: #47978).
+  * Restored echo's option processing ability.
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 22 Oct 1999 10:20:58 +1000
+
+ash (0.3.5-7) unstable; urgency=low
+
+  * echo no longer supports options.
+  * Don't quote patterns inside parameter substitutions enclosed by double
+    quotes (closes: #47842).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 20 Oct 1999 20:28:14 +1000
+
+ash (0.3.5-6) unstable; urgency=low
+
+  * Use getcwd() instead of /bin/pwd -- Zack Weinberg (closes: #46981).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 10 Oct 1999 16:31:49 +1000
+
+ash (0.3.5-5) unstable; urgency=low
+
+  * Only test for -e on simple commands (fixes #44559).
+
+ -- Herbert Xu <herbert@debian.org>  Wed,  8 Sep 1999 22:18:27 +1000
+
+ash (0.3.5-4) unstable; urgency=low
+
+  * Don't wait for stopped children if job control is disabled (fixes #42814).
+  * Allow an option '(' in a case statement (fixes #42364).
+
+ -- Herbert Xu <herbert@debian.org>  Thu, 12 Aug 1999 23:30:30 +1000
+
+ash (0.3.5-3) unstable; urgency=low
+
+  * OK, the fix to the esoteric problem in 0.3.5-1 actually breaks VSASSIGN
+    and VSQUESTION, they should work properly now (fixes #41327).
+
+ -- Herbert Xu <herbert@debian.org>  Thu, 15 Jul 1999 22:47:13 +1000
+
+ash (0.3.5-2) unstable; urgency=low
+
+  * PATH search and execution is now correct.
+  * hash no longer shows builtins.
+  * Added kill builtin.
+  * New description from James R. van Zandt reformatted by Josip Rodin.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 12 Jul 1999 18:51:42 +1000
+
+ash (0.3.5-1) unstable; urgency=low
+
+  * New upstream release.
+  * Adapted to new pmake (fixes #38737).
+  * Fixed behvaiour of backslashes preceding a closing brace for a parameter
+    substituion inside double quotes (even bash messes this one up :).
+  * Fixed command (fixes #34639).
+  * Fixed a pipe bug where stdin may be wrongly closed (fixes #35452).
+  * Revamped getopts (fixes #39694).
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  4 Jul 1999 12:19:01 +1000
+
+ash (0.3.4-7) unstable; urgency=low
+
+  * Fixed a glibc 2.1 compatitibility problem.
+  * Fixed a PWD inconsistency that stuffed up the kernel compilation.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 17 May 1999 23:14:57 +1000
+
+ash (0.3.4-6) unstable; urgency=low
+
+  * Fixed incorrect -e test due to the last bug fix (fixes #26509).
+
+ -- Herbert Xu <herbert@debian.org>  Tue,  8 Sep 1998 10:02:46 +1000
+
+ash (0.3.4-5) unstable; urgency=low
+
+  * Use test_eaccess from bash instead of access(2) (fixes #26110).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 26 Aug 1998 21:22:49 +1000
+
+ash (0.3.4-4) unstable; urgency=low
+
+  * Only upload to unstable.
+
+ -- Herbert Xu <herbert@debian.org>  Tue,  5 May 1998 18:01:02 +1000
+
+ash (0.3.4-3) frozen unstable; urgency=low
+
+  * Applied sparc patch (fixes #21562).
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  1 May 1998 19:48:13 +1000
+
+ash (0.3.4-2) frozen unstable; urgency=low
+
+  * Fixed the incorrect trap fixes (fixes #20363).
+
+ -- Herbert Xu <herbert@debian.org>  Thu, 16 Apr 1998 21:07:10 +1000
+
+ash (0.3.4-1) unstable; urgency=low
+
+  * New upstream release.
+  * Reverted word splitting change in 0.3.2-1 since the fix was broken and
+    major work (the quote removal is done too quickly at the moment) is needed
+    to fix it properly.
+  * Fixed more trap noncompliance.
+
+ -- Herbert Xu <herbert@debian.org>  Thu, 19 Mar 1998 22:59:12 +1100
+
+ash (0.3.2-5) unstable; urgency=low
+
+  * Fixed a bug when doing pattern matching in parameter expansions.
+
+ -- Herbert Xu <herbert@debian.org>  Tue, 10 Mar 1998 21:25:40 +1100
+
+ash (0.3.2-4) unstable; urgency=low
+
+  * Allow ] to be quoted in bracket expressions (fixes #17533).
+  * Move dh_fixperms to second last spot (fixes #18267).
+  * Don't do field splitting in evalfor.
+
+ -- Herbert Xu <herbert@debian.org>  Tue, 17 Feb 1998 13:32:09 +1100
+
+ash (0.3.2-3) unstable; urgency=low
+
+  * Fixed stupid core dump.
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 11 Feb 1998 21:33:55 +1100
+
+ash (0.3.2-2) unstable; urgency=low
+
+  * Hack for special builtins (fixes #18055).
+  * Hack for command.
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 11 Feb 1998 21:19:46 +1100
+
+ash (0.3.2-1) unstable; urgency=low
+
+  * NetBSD-current version as of 19980209.
+  * Fixed a word splitting problem after parameter expansion thanks to Alexey
+    Marinichev.
+  * Converted to debhelper (fixes #14612, #15005).
+
+ -- Herbert Xu <herbert@debian.org>  Mon,  9 Feb 1998 16:53:48 +1100
+
+ash (0.3.1-20) unstable; urgency=low
+
+  * Fixed -e problem with eval.
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  7 Dec 1997 20:19:00 +1100
+
+ash (0.3.1-19) unstable; urgency=low
+
+  * Fixed -e problem with command substitution.
+
+ -- Herbert Xu <herbert@debian.org>  Sun,  7 Dec 1997 19:44:49 +1100
+
+ash (0.3.1-18) unstable; urgency=low
+
+  * Do not link with ncurses (#15485).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 30 Nov 1997 12:00:11 +1100
+
+ash (0.3.1-17) unstable; urgency=low
+
+  * Set PATH like bash (#15238).
+
+ -- Herbert Xu <herbert@debian.org>  Wed, 26 Nov 1997 16:17:27 +1100
+
+ash (0.3.1-16) unstable; urgency=low
+
+  * Fixed incorrect assignment builtin code.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 24 Nov 1997 16:19:10 +1100
+
+ash (0.3.1-15) unstable; urgency=low
+
+  * hash now returns error codes (needed by the Linux kernel).
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 23 Nov 1997 21:37:08 +1100
+
+ash (0.3.1-14) unstable; urgency=low
+
+  * Disabled word-splitting for assignment builtins.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 23 Nov 1997 12:45:15 +1100
+
+ash (0.3.1-13) unstable; urgency=low
+
+  * ! is now recognised even after &&/||.
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 21 Nov 1997 22:09:05 +1100
+
+ash (0.3.1-12) unstable; urgency=low
+
+  * More fixes to the handling of SIGINT when forking.
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 14 Nov 1997 15:14:32 +1100
+
+ash (0.3.1-11) unstable; urgency=low
+
+  * Ignore SIGINT when forking non-interactively.
+
+ -- Herbert Xu <herbert@debian.org>  Mon,  3 Nov 1997 12:00:02 +1100
+
+ash (0.3.1-10) unstable; urgency=low
+
+  * echo now handles options correctly.
+  * echo nolonger returns 0 if erorrs occured while writing to stdout.
+  * New code from GNU echo merged.
+  * Error messages from test now work.
+
+ -- Herbert Xu <herbert@debian.org>  Wed,  8 Oct 1997 21:47:13 +1000
+
+ash (0.3.1-9) unstable; urgency=low
+
+  * ! is recognised at pipeline level like bash.
+
+ -- Herbert Xu <herbert@debian.org>  Mon, 15 Sep 1997 23:13:45 +1000
+
+ash (0.3.1-8) unstable; urgency=medium
+
+  * Old patch regarding SIGCHLD in again.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 31 Aug 1997 11:20:27 +1000
+
+ash (0.3.1-7) unstable; urgency=low
+
+  * /bin/sh -e is behaving even better now (for loops within conditionals).
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 23 Aug 1997 22:08:19 +1000
+
+ash (0.3.1-6) unstable; urgency=low
+
+  * /bin/sh -e is behaving better now.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 23 Aug 1997 13:16:26 +1000
+
+ash (0.3.1-5) unstable; urgency=low
+
+  * hash -v /dir/command doesn't coredump anymore.
+  * type /dir/command now works correctly.
+
+ -- Herbert Xu <herbert@debian.org>  Fri,  1 Aug 1997 20:48:19 +1000
+
+ash (0.3.1-4) unstable; urgency=low
+
+  * trap now understands symbolic signal names.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 26 Jul 1997 14:04:46 +1000
+
+ash (0.3.1-3) unstable; urgency=low
+
+  * Added the builtin test command.
+
+ -- Herbert Xu <herbert@debian.org>  Sun, 20 Jul 1997 15:00:14 +1000
+
+ash (0.3.1-2) unstable; urgency=medium
+
+  * Fixed a coredump involving $*.
+
+ -- Herbert Xu <herbert@debian.org>  Sat, 19 Jul 1997 12:03:02 +1000
+
+ash (0.3.1-1) unstable; urgency=medium
+
+  * NetBSD-current version as of 19970715.
+  * Fixed a "use after free" bug (#11294).
+
+ -- Herbert Xu <herbert@debian.org>  Fri, 18 Jul 1997 13:48:09 +1000
+
+ash (0.3-1) unstable; urgency=low
+
+  * Initial Release.
+
+ -- Herbert Xu <herbert@debian.org>  Thu, 19 Jun 1997 19:29:16 +1000
+
diff --git a/bin/dash/Makefile.am b/bin/dash/Makefile.am
new file mode 100644
index 00000000..af437a64
--- /dev/null
+++ b/bin/dash/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src
diff --git a/bin/dash/Makefile.in b/bin/dash/Makefile.in
new file mode 100644
index 00000000..49084bfd
--- /dev/null
+++ b/bin/dash/Makefile.in
@@ -0,0 +1,776 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+	$(am__configure_deps) $(am__DIST_COMMON)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+	ctags-recursive dvi-recursive html-recursive info-recursive \
+	install-data-recursive install-dvi-recursive \
+	install-exec-recursive install-html-recursive \
+	install-info-recursive install-pdf-recursive \
+	install-ps-recursive install-recursive installcheck-recursive \
+	installdirs-recursive pdf-recursive ps-recursive \
+	tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
+  distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+  $(RECURSIVE_TARGETS) \
+  $(RECURSIVE_CLEAN_TARGETS) \
+  $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+	cscope distdir distdir-am dist dist-all distcheck
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \
+	config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in COPYING \
+	ChangeLog compile install-sh missing
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  if test -d "$(distdir)"; then \
+    find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+      && rm -rf "$(distdir)" \
+      || { sleep 5 && rm -rf "$(distdir)"; }; \
+  else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+DIST_TARGETS = dist-gzip
+# Exists only to be overridden by the user if desired.
+AM_DISTCHECK_DVI_TARGET = dvi
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+  | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src
+all: config.h
+	$(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh: Makefile
+	@:
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \
+	      $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \
+		&& exit 0; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    echo ' $(SHELL) ./config.status'; \
+	    $(SHELL) ./config.status;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	$(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	$(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+	@test -f $@ || rm -f stamp-h1
+	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+	@rm -f stamp-h1
+	cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in:  $(am__configure_deps) 
+	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+	rm -f stamp-h1
+	touch $@
+
+distclean-hdr:
+	-rm -f config.h stamp-h1
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+#     (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+	@fail=; \
+	if $(am__make_keepgoing); then \
+	  failcom='fail=yes'; \
+	else \
+	  failcom='exit 1'; \
+	fi; \
+	dot_seen=no; \
+	target=`echo $@ | sed s/-recursive//`; \
+	case "$@" in \
+	  distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+	  *) list='$(SUBDIRS)' ;; \
+	esac; \
+	for subdir in $$list; do \
+	  echo "Making $$target in $$subdir"; \
+	  if test "$$subdir" = "."; then \
+	    dot_seen=yes; \
+	    local_target="$$target-am"; \
+	  else \
+	    local_target="$$target"; \
+	  fi; \
+	  ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+	  || eval $$failcom; \
+	done; \
+	if test "$$dot_seen" = "no"; then \
+	  $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+	fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+	  include_option=--etags-include; \
+	  empty_fix=.; \
+	else \
+	  include_option=--include; \
+	  empty_fix=; \
+	fi; \
+	list='$(SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    test ! -f $$subdir/TAGS || \
+	      set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+	  fi; \
+	done; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+	test ! -s cscope.files \
+	  || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+	-rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+distdir: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+	$(am__remove_distdir)
+	test -d "$(distdir)" || mkdir "$(distdir)"
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+	@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+	  if test "$$subdir" = .; then :; else \
+	    $(am__make_dryrun) \
+	      || test -d "$(distdir)/$$subdir" \
+	      || $(MKDIR_P) "$(distdir)/$$subdir" \
+	      || exit 1; \
+	    dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+	    $(am__relativize); \
+	    new_distdir=$$reldir; \
+	    dir1=$$subdir; dir2="$(top_distdir)"; \
+	    $(am__relativize); \
+	    new_top_distdir=$$reldir; \
+	    echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+	    echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+	    ($(am__cd) $$subdir && \
+	      $(MAKE) $(AM_MAKEFLAGS) \
+	        top_distdir="$$new_top_distdir" \
+	        distdir="$$new_distdir" \
+		am__remove_distdir=: \
+		am__skip_length_check=: \
+		am__skip_mode_fix=: \
+	        distdir) \
+	      || exit 1; \
+	  fi; \
+	done
+	-test -n "$(am__skip_mode_fix)" \
+	|| find "$(distdir)" -type d ! -perm -755 \
+		-exec chmod u+rwx,go+rx {} \; -o \
+	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+	  ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+	|| chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+	tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
+	$(am__post_remove_distdir)
+
+dist-bzip2: distdir
+	tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+	$(am__post_remove_distdir)
+
+dist-lzip: distdir
+	tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+	$(am__post_remove_distdir)
+
+dist-xz: distdir
+	tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+	$(am__post_remove_distdir)
+
+dist-zstd: distdir
+	tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst
+	$(am__post_remove_distdir)
+
+dist-tarZ: distdir
+	@echo WARNING: "Support for distribution archives compressed with" \
+		       "legacy program 'compress' is deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+	$(am__post_remove_distdir)
+
+dist-shar: distdir
+	@echo WARNING: "Support for shar distribution archives is" \
+	               "deprecated." >&2
+	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+	shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
+	$(am__post_remove_distdir)
+
+dist-zip: distdir
+	-rm -f $(distdir).zip
+	zip -rq $(distdir).zip $(distdir)
+	$(am__post_remove_distdir)
+
+dist dist-all:
+	$(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+	$(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+	case '$(DIST_ARCHIVES)' in \
+	*.tar.gz*) \
+	  eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
+	*.tar.bz2*) \
+	  bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+	*.tar.lz*) \
+	  lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+	*.tar.xz*) \
+	  xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+	*.tar.Z*) \
+	  uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+	*.shar.gz*) \
+	  eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
+	*.zip*) \
+	  unzip $(distdir).zip ;;\
+	*.tar.zst*) \
+	  zstd -dc $(distdir).tar.zst | $(am__untar) ;;\
+	esac
+	chmod -R a-w $(distdir)
+	chmod u+w $(distdir)
+	mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
+	chmod a-w $(distdir)
+	test -d $(distdir)/_build || exit 0; \
+	dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+	  && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+	  && am__cwd=`pwd` \
+	  && $(am__cd) $(distdir)/_build/sub \
+	  && ../../configure \
+	    $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+	    $(DISTCHECK_CONFIGURE_FLAGS) \
+	    --srcdir=../.. --prefix="$$dc_install_base" \
+	  && $(MAKE) $(AM_MAKEFLAGS) \
+	  && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \
+	  && $(MAKE) $(AM_MAKEFLAGS) check \
+	  && $(MAKE) $(AM_MAKEFLAGS) install \
+	  && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+	  && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+	  && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+	        distuninstallcheck \
+	  && chmod -R a-w "$$dc_install_base" \
+	  && ({ \
+	       (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+	       && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+	            distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+	      } || { rm -rf "$$dc_destdir"; exit 1; }) \
+	  && rm -rf "$$dc_destdir" \
+	  && $(MAKE) $(AM_MAKEFLAGS) dist \
+	  && rm -rf $(DIST_ARCHIVES) \
+	  && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+	  && cd "$$am__cwd" \
+	  || exit 1
+	$(am__post_remove_distdir)
+	@(echo "$(distdir) archives ready for distribution: "; \
+	  list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+	  sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+	@test -n '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: trying to run $@ with an empty' \
+	       '$$(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	$(am__cd) '$(distuninstallcheck_dir)' || { \
+	  echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+	  exit 1; \
+	}; \
+	test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+	   || { echo "ERROR: files left after uninstall:" ; \
+	        if test -n "$(DESTDIR)"; then \
+	          echo "  (check DESTDIR support)"; \
+	        fi ; \
+	        $(distuninstallcheck_listfiles) ; \
+	        exit 1; } >&2
+distcleancheck: distclean
+	@if test '$(srcdir)' = . ; then \
+	  echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+	  exit 1 ; \
+	fi
+	@test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+	  || { echo "ERROR: files left in build directory after distclean:" ; \
+	       $(distcleancheck_listfiles) ; \
+	       exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+	-rm -f $(am__CONFIG_DISTCLEAN_FILES)
+	-rm -rf $(top_srcdir)/autom4te.cache
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) all install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+	am--refresh check check-am clean clean-cscope clean-generic \
+	cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \
+	dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \
+	dist-zstd distcheck distclean distclean-generic distclean-hdr \
+	distclean-tags distcleancheck distdir distuninstallcheck dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-ps install-ps-am install-strip \
+	installcheck installcheck-am installdirs installdirs-am \
+	maintainer-clean maintainer-clean-generic mostlyclean \
+	mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/dash/aclocal.m4 b/bin/dash/aclocal.m4
new file mode 100644
index 00000000..6715ee0e
--- /dev/null
+++ b/bin/dash/aclocal.m4
@@ -0,0 +1,1132 @@
+# generated automatically by aclocal 1.16.3 -*- Autoconf -*-
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# Copyright (C) 2002-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.16'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.16.3], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.16.3])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'.  In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC],   [depcc="$CC"   am_compiler_list=],
+      [$1], [CXX],  [depcc="$CXX"  am_compiler_list=],
+      [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+      [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+      [$1], [UPC],  [depcc="$UPC"  am_compiler_list=],
+      [$1], [GCJ],  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                    [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+  [--enable-dependency-tracking],
+  [do not reject slow dependency extractors])
+AS_HELP_STRING(
+  [--disable-dependency-tracking],
+  [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  AS_CASE([$CONFIG_FILES],
+          [*\'*], [eval set x "$CONFIG_FILES"],
+          [*], [set x $CONFIG_FILES])
+  shift
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
+  do
+    # Strip MF so we end up with the name of the file.
+    am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`AS_DIRNAME(["$am_mf"])`
+    am_filepart=`AS_BASENAME(["$am_mf"])`
+    AM_RUN_LOG([cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles]) || am_rc=$?
+  done
+  if test $am_rc -ne 0; then
+    AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  If GNU make was not used, consider
+    re-running the configure script with MAKE="gmake" (or whatever is
+    necessary).  You can also try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).])
+  fi
+  AS_UNSET([am_dirpart])
+  AS_UNSET([am_filepart])
+  AS_UNSET([am_mf])
+  AS_UNSET([am_rc])
+  rm -f conftest-deps.mk
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking is enabled.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
+# order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+             [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+  m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+  [ok:ok],,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+	      [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+			     [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+		  [_AM_DEPENDENCIES([CC])],
+		  [m4_define([AC_PROG_CC],
+			     m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+		  [_AM_DEPENDENCIES([CXX])],
+		  [m4_define([AC_PROG_CXX],
+			     m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+		  [_AM_DEPENDENCIES([OBJC])],
+		  [m4_define([AC_PROG_OBJC],
+			     m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+		  [_AM_DEPENDENCIES([OBJCXX])],
+		  [m4_define([AC_PROG_OBJCXX],
+			     m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+  fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes.	            -*- Autoconf -*-
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
+am__doit:
+	@echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+  AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+      ['0:this is the am__doit target'],
+      [AS_CASE([$s],
+          [BSD], [am__include='.include' am__quote='"'],
+          [am__include='include' am__quote=''])])
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+  [whether $CC understands -c and -o together],
+  [am_cv_prog_cc_c_o],
+  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \	]]*)
+    AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$[*]" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$[*]" != "X $srcdir/configure conftest.file" \
+	&& test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment])
+     fi
+     if test "$[2]" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+  [AC_MSG_CHECKING([that generated files are newer than configure])
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+  [--enable-silent-rules],
+  [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+  [--disable-silent-rules],
+  [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+   [am_cv_make_support_nested_variables],
+   [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+  dnl Using '$V' instead of '$(V)' breaks IRIX make.
+  AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004-2020 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+  [m4_case([$1],
+    [ustar],
+     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+      # There is notably a 21 bits limit for the UID and the GID.  In fact,
+      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+      # and bug#13588).
+      am_max_uid=2097151 # 2^21 - 1
+      am_max_gid=$am_max_uid
+      # The $UID and $GID variables are not portable, so we need to resort
+      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
+      # below are definitely unexpected, so allow the users to see them
+      # (that is, avoid stderr redirection).
+      am_uid=`id -u || echo unknown`
+      am_gid=`id -g || echo unknown`
+      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+      if test $am_uid -le $am_max_uid; then
+         AC_MSG_RESULT([yes])
+      else
+         AC_MSG_RESULT([no])
+         _am_tools=none
+      fi
+      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+      if test $am_gid -le $am_max_gid; then
+         AC_MSG_RESULT([yes])
+      else
+        AC_MSG_RESULT([no])
+        _am_tools=none
+      fi],
+
+  [pax],
+    [],
+
+  [m4_fatal([Unknown tar format])])
+
+  AC_MSG_CHECKING([how to create a $1 tar archive])
+
+  # Go ahead even if we have the value already cached.  We do so because we
+  # need to set the values for the 'am__tar' and 'am__untar' variables.
+  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+  for _am_tool in $_am_tools; do
+    case $_am_tool in
+    gnutar)
+      for _am_tar in tar gnutar gtar; do
+        AM_RUN_LOG([$_am_tar --version]) && break
+      done
+      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+      am__untar="$_am_tar -xf -"
+      ;;
+    plaintar)
+      # Must skip GNU tar: if it does not support --format= it doesn't create
+      # ustar tarball either.
+      (tar --version) >/dev/null 2>&1 && continue
+      am__tar='tar chf - "$$tardir"'
+      am__tar_='tar chf - "$tardir"'
+      am__untar='tar xf -'
+      ;;
+    pax)
+      am__tar='pax -L -x $1 -w "$$tardir"'
+      am__tar_='pax -L -x $1 -w "$tardir"'
+      am__untar='pax -r'
+      ;;
+    cpio)
+      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+      am__untar='cpio -i -H $1 -d'
+      ;;
+    none)
+      am__tar=false
+      am__tar_=false
+      am__untar=false
+      ;;
+    esac
+
+    # If the value was cached, stop now.  We just wanted to have am__tar
+    # and am__untar set.
+    test -n "${am_cv_prog_tar_$1}" && break
+
+    # tar/untar a dummy directory, and stop if the command works.
+    rm -rf conftest.dir
+    mkdir conftest.dir
+    echo GrepMe > conftest.dir/file
+    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+    rm -rf conftest.dir
+    if test -s conftest.tar; then
+      AM_RUN_LOG([$am__untar <conftest.tar])
+      AM_RUN_LOG([cat conftest.dir/file])
+      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+    fi
+  done
+  rm -rf conftest.dir
+
+  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
diff --git a/bin/dash/autogen.sh b/bin/dash/autogen.sh
new file mode 100755
index 00000000..5e9006ca
--- /dev/null
+++ b/bin/dash/autogen.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+aclocal \
+&& autoheader \
+&& automake --add-missing --copy \
+&& autoconf
diff --git a/bin/dash/compile b/bin/dash/compile
new file mode 100755
index 00000000..23fcba01
--- /dev/null
+++ b/bin/dash/compile
@@ -0,0 +1,348 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" ""	$nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+  file=$1
+  case $file in
+    / | /[!/]*) # absolute file, and not a UNC file
+      if test -z "$file_conv"; then
+	# lazily determine how to convert abs files
+	case `uname -s` in
+	  MINGW*)
+	    file_conv=mingw
+	    ;;
+	  CYGWIN* | MSYS*)
+	    file_conv=cygwin
+	    ;;
+	  *)
+	    file_conv=wine
+	    ;;
+	esac
+      fi
+      case $file_conv/,$2, in
+	*,$file_conv,*)
+	  ;;
+	mingw/*)
+	  file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+	  ;;
+	cygwin/* | msys/*)
+	  file=`cygpath -m "$file" || echo "$file"`
+	  ;;
+	wine/*)
+	  file=`winepath -w "$file" || echo "$file"`
+	  ;;
+      esac
+      ;;
+  esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+    if test -f "$dir/lib$lib.a"; then
+      found=yes
+      lib=$dir/lib$lib.a
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+  # Assume a capable shell
+  lib_path=
+  shared=:
+  linker_opts=
+  for arg
+  do
+    if test -n "$eat"; then
+      eat=
+    else
+      case $1 in
+	-o)
+	  # configure might choose to run compile as 'compile cc -o foo foo.c'.
+	  eat=1
+	  case $2 in
+	    *.o | *.[oO][bB][jJ])
+	      func_file_conv "$2"
+	      set x "$@" -Fo"$file"
+	      shift
+	      ;;
+	    *)
+	      func_file_conv "$2"
+	      set x "$@" -Fe"$file"
+	      shift
+	      ;;
+	  esac
+	  ;;
+	-I)
+	  eat=1
+	  func_file_conv "$2" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-I*)
+	  func_file_conv "${1#-I}" mingw
+	  set x "$@" -I"$file"
+	  shift
+	  ;;
+	-l)
+	  eat=1
+	  func_cl_dashl "$2"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-l*)
+	  func_cl_dashl "${1#-l}"
+	  set x "$@" "$lib"
+	  shift
+	  ;;
+	-L)
+	  eat=1
+	  func_cl_dashL "$2"
+	  ;;
+	-L*)
+	  func_cl_dashL "${1#-L}"
+	  ;;
+	-static)
+	  shared=false
+	  ;;
+	-Wl,*)
+	  arg=${1#-Wl,}
+	  save_ifs="$IFS"; IFS=','
+	  for flag in $arg; do
+	    IFS="$save_ifs"
+	    linker_opts="$linker_opts $flag"
+	  done
+	  IFS="$save_ifs"
+	  ;;
+	-Xlinker)
+	  eat=1
+	  linker_opts="$linker_opts $2"
+	  ;;
+	-*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+	*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+	  func_file_conv "$1"
+	  set x "$@" -Tp"$file"
+	  shift
+	  ;;
+	*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+	  func_file_conv "$1" mingw
+	  set x "$@" "$file"
+	  shift
+	  ;;
+	*)
+	  set x "$@" "$1"
+	  shift
+	  ;;
+      esac
+    fi
+    shift
+  done
+  if test -n "$linker_opts"; then
+    linker_opts="-link$linker_opts"
+  fi
+  exec "$@" $linker_opts
+  exit 1
+}
+
+eat=
+
+case $1 in
+  '')
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit $?
+    ;;
+  cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
+  icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
+    func_cl_wrapper "$@"      # Doesn't return...
+    ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+  if test -n "$eat"; then
+    eat=
+  else
+    case $1 in
+      -o)
+	# configure might choose to run compile as 'compile cc -o foo foo.c'.
+	# So we strip '-o arg' only if arg is an object.
+	eat=1
+	case $2 in
+	  *.o | *.obj)
+	    ofile=$2
+	    ;;
+	  *)
+	    set x "$@" -o "$2"
+	    shift
+	    ;;
+	esac
+	;;
+      *.c)
+	cfile=$1
+	set x "$@" "$1"
+	shift
+	;;
+      *)
+	set x "$@" "$1"
+	shift
+	;;
+    esac
+  fi
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no '-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # '.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+  if mkdir "$lockdir" >/dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+  test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+  test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/bin/dash/config.h.in b/bin/dash/config.h.in
new file mode 100644
index 00000000..6fb0b3fb
--- /dev/null
+++ b/bin/dash/config.h.in
@@ -0,0 +1,205 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define if __attribute__((__alias__())) is supported */
+#undef HAVE_ALIAS_ATTRIBUTE
+
+/* Define to 1 if you have the <alloca.h> header file. */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the `bsearch' function. */
+#undef HAVE_BSEARCH
+
+/* Define to 1 if you have the declaration of `isblank', and to 0 if you
+   don't. */
+#undef HAVE_DECL_ISBLANK
+
+/* Define to 1 if you have the `faccessat' function. */
+#undef HAVE_FACCESSAT
+
+/* Define to 1 if you have the `fnmatch' function. */
+#undef HAVE_FNMATCH
+
+/* Define to 1 if you have the `getpwnam' function. */
+#undef HAVE_GETPWNAM
+
+/* Define to 1 if you have the `getrlimit' function. */
+#undef HAVE_GETRLIMIT
+
+/* Define to 1 if you have the `glob' function. */
+#undef HAVE_GLOB
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `isalpha' function. */
+#undef HAVE_ISALPHA
+
+/* Define to 1 if you have the `killpg' function. */
+#undef HAVE_KILLPG
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `mempcpy' function. */
+#undef HAVE_MEMPCPY
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define to 1 if you have the `sigsetmask' function. */
+#undef HAVE_SIGSETMASK
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `stpcpy' function. */
+#undef HAVE_STPCPY
+
+/* Define to 1 if you have the `strchrnul' function. */
+#undef HAVE_STRCHRNUL
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strsignal' function. */
+#undef HAVE_STRSIGNAL
+
+/* Define to 1 if you have the `strtod' function. */
+#undef HAVE_STRTOD
+
+/* Define to 1 if you have the `strtoimax' function. */
+#undef HAVE_STRTOIMAX
+
+/* Define to 1 if you have the `strtoumax' function. */
+#undef HAVE_STRTOUMAX
+
+/* Define if your `struct stat' has `st_mtim' */
+#undef HAVE_ST_MTIM
+
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define if your faccessat tells root all files are executable */
+#undef HAVE_TRADITIONAL_FACCESSAT
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `_el_fn_sh_complete' function. */
+#undef HAVE__EL_FN_SH_COMPLETE
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to printf format string for intmax_t */
+#undef PRIdMAX
+
+/* The size of `intmax_t', as computed by sizeof. */
+#undef SIZEOF_INTMAX_T
+
+/* The size of `long long int', as computed by sizeof. */
+#undef SIZEOF_LONG_LONG_INT
+
+/* Define if you build with -DSMALL */
+#undef SMALL
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable extensions on AIX 3, Interix.  */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris.  */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if you build with -DWITH_LINENO */
+#undef WITH_LINENO
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to system shell path */
+#undef _PATH_BSHELL
+
+/* Define to devnull device node path */
+#undef _PATH_DEVNULL
+
+/* Define to tty device node path */
+#undef _PATH_TTY
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+   this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* 64-bit operations are the same as 32-bit */
+#undef dirent64
+
+/* 64-bit operations are the same as 32-bit */
+#undef fstat64
+
+/* 64-bit operations are the same as 32-bit */
+#undef lstat64
+
+/* 64-bit operations are the same as 32-bit */
+#undef open64
+
+/* 64-bit operations are the same as 32-bit */
+#undef readdir64
+
+/* klibc has bsd_signal instead of signal */
+#undef signal
+
+/* 64-bit operations are the same as 32-bit */
+#undef stat64
diff --git a/bin/dash/configure b/bin/dash/configure
new file mode 100755
index 00000000..83889b3b
--- /dev/null
+++ b/bin/dash/configure
@@ -0,0 +1,6450 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for dash 0.5.11.2.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='dash'
+PACKAGE_TARNAME='dash'
+PACKAGE_VERSION='0.5.11.2'
+PACKAGE_STRING='dash 0.5.11.2'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="src/main.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+CC_FOR_BUILD
+EGREP
+GREP
+CPP
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL
+am__quote'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_dependency_tracking
+enable_static
+enable_fnmatch
+enable_glob
+enable_test_workaround
+with_libedit
+enable_lineno
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures dash 0.5.11.2 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/dash]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of dash 0.5.11.2:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-silent-rules   less verbose build output (undo: "make V=1")
+  --disable-silent-rules  verbose build output (undo: "make V=0")
+  --enable-dependency-tracking
+                          do not reject slow dependency extractors
+  --disable-dependency-tracking
+                          speeds up one-time build
+  --enable-static         Build statical linked program
+  --enable-fnmatch        Use fnmatch(3) from libc
+  --enable-glob           Use glob(3) from libc
+  --enable-test-workaround
+                          Guard against faccessat(2) that tells root all files
+                          are executable
+  --disable-lineno        Disable LINENO support
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --without-libedit       Compile without libedit support
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CPP         C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+dash configure 0.5.11.2
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if test "$cross_compiling" = yes; then
+    # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=0 ac_mid=0
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid; break
+else
+  as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+			if test $ac_lo -le $ac_mid; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=-1 ac_mid=-1
+  while :; do
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_lo=$ac_mid; break
+else
+  as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+			if test $ac_mid -le $ac_hi; then
+			  ac_lo= ac_hi=
+			  break
+			fi
+			as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  done
+else
+  ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+  as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_hi=$ac_mid
+else
+  as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+  else
+    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+  FILE *f = fopen ("conftest.val", "w");
+  if (! f)
+    return 1;
+  if (($2) < 0)
+    {
+      long int i = longval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%ld", i);
+    }
+  else
+    {
+      unsigned long int i = ulongval ();
+      if (i != ($2))
+	return 1;
+      fprintf (f, "%lu", i);
+    }
+  /* Do not output a trailing newline, as this causes \r\n confusion
+     on some platforms.  */
+  return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+  ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+  fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_compute_int
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by dash $as_me 0.5.11.2, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+am__api_version='1.16'
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+  ./ | .// | /[cC]/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+	if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+	  if test $ac_prog = install &&
+	    grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # AIX install.  It has an incompatible calling convention.
+	    :
+	  elif test $ac_prog = install &&
+	    grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+	    # program-specific install script used by HP pwplus--don't use.
+	    :
+	  else
+	    rm -rf conftest.one conftest.two conftest.dir
+	    echo one > conftest.one
+	    echo two > conftest.two
+	    mkdir conftest.dir
+	    if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+	      test -s conftest.one && test -s conftest.two &&
+	      test -s conftest.dir/conftest.one &&
+	      test -s conftest.dir/conftest.two
+	    then
+	      ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+	      break 3
+	    fi
+	  fi
+	fi
+      done
+    done
+    ;;
+esac
+
+  done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \	]*)
+    as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   am_has_slept=no
+   for am_try in 1 2; do
+     echo "timestamp, slept: $am_has_slept" > conftest.file
+     set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+     if test "$*" = "X"; then
+	# -L didn't work.
+	set X `ls -t "$srcdir/configure" conftest.file`
+     fi
+     if test "$*" != "X $srcdir/configure conftest.file" \
+	&& test "$*" != "X conftest.file $srcdir/configure"; then
+
+	# If neither matched, then we have a broken ls.  This can happen
+	# if, for instance, CONFIG_SHELL is bash and it inherits a
+	# broken ls alias from the environment.  This has actually
+	# happened.  Such a system could not be considered "sane".
+	as_fn_error $? "ls -t appears to fail.  Make sure there is not a broken
+  alias in your environment" "$LINENO" 5
+     fi
+     if test "$2" = conftest.file || test $am_try -eq 2; then
+       break
+     fi
+     # Just in case.
+     sleep 1
+     am_has_slept=yes
+   done
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+  ( sleep 1 ) &
+  am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  MISSING="\${SHELL} '$am_aux_dir/missing'"
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+  am_missing_run="$MISSING "
+else
+  am_missing_run=
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\	*)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip".  However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if ${ac_cv_path_mkdir+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in mkdir gmkdir; do
+	 for ac_exec_ext in '' $ac_executable_extensions; do
+	   as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+	   case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+	     'mkdir (GNU coreutils) '* | \
+	     'mkdir (coreutils) '* | \
+	     'mkdir (fileutils) '4.1*)
+	       ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+	       break 3;;
+	   esac
+	 done
+       done
+  done
+IFS=$as_save_IFS
+
+fi
+
+  test -d ./--version && rmdir ./--version
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+	@echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='dash'
+ VERSION='0.5.11.2'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility.  To be removed once Automake 1.9.x
+# dies out for good.  For more background, see:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver).  The
+# system "awk" is bad on some platforms.
+# Always define AMTAR for backward compatibility.  Yes, it's still used
+# in the wild :-(  We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar  pax cpio none'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes.  So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+  cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present.  This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message.  This
+can help us improve future automake versions.
+
+END
+  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+    echo 'Configuration will proceed anyway, since you have set the' >&2
+    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+    echo >&2
+  else
+    cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+  fi
+fi
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+  enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+  yes) AM_DEFAULT_VERBOSITY=0;;
+   no) AM_DEFAULT_VERBOSITY=1;;
+    *) AM_DEFAULT_VERBOSITY=0;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+	@$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+  am_cv_make_support_nested_variables=yes
+else
+  am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+    AM_V='$(V)'
+  AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+  AM_V=$AM_DEFAULT_VERBOSITY
+  AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+  # Make sure it works both with $CC and with simple cc.
+  # Following AC_PROG_CC_C_O, we do the test twice because some
+  # compilers refuse to overwrite an existing .o file with -o,
+  # though they will create one.
+  am_cv_prog_cc_c_o=yes
+  for am_i in 1 2; do
+    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } \
+         && test -f conftest2.$ac_objext; then
+      : OK
+    else
+      am_cv_prog_cc_c_o=no
+      break
+    fi
+  done
+  rm -f core conftest*
+  unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
+cat > confinc.mk << 'END'
+am__doit:
+	@echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+  { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
+   (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); }
+  case $?:`cat confinc.out 2>/dev/null` in #(
+  '0:this is the am__doit target') :
+    case $s in #(
+  BSD) :
+    am__include='.include' am__quote='"' ;; #(
+  *) :
+    am__include='include' am__quote='' ;;
+esac ;; #(
+  *) :
+     ;;
+esac
+  if test "$am__include" != "#"; then
+    _am_result="yes ($s style)"
+    break
+  fi
+done
+rm -f confinc.* confmf.*
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+$as_echo "${_am_result}" >&6; }
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+  am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named 'D' -- because '-MD' means "put the output
+  # in D".
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+      # Solaris 10 /bin/sh.
+      echo '/* dummy */' > sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with '-c' and '-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle '-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs.
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # After this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested.
+      if test "x$enable_dependency_tracking" = xyes; then
+	continue
+      else
+	break
+      fi
+      ;;
+    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+      # This compiler won't grok '-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+  ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+  MINIX=yes
+else
+  MINIX=
+fi
+
+
+  if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#         define __EXTENSIONS__ 1
+          $ac_includes_default
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_safe_to_define___extensions__=yes
+else
+  ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+  test $ac_cv_safe_to_define___extensions__ = yes &&
+    $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+  $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+  $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+  $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for build system compiler" >&5
+$as_echo_n "checking for build system compiler... " >&6; }
+if test "$cross_compiling" = yes; then
+	CC_FOR_BUILD=${CC_FOR_BUILD-cc}
+else
+	CC_FOR_BUILD=${CC}
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${CC_FOR_BUILD}" >&5
+$as_echo "${CC_FOR_BUILD}" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__((__alias__()))" >&5
+$as_echo_n "checking for __attribute__((__alias__()))... " >&6; }
+dash_cv_have_attribute_alias=no
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+void t() {}
+                                 void a() __attribute__((__alias__("t")));
+int
+main ()
+{
+a();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  dash_cv_have_attribute_alias=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dash_cv_have_attribute_alias" >&5
+$as_echo "$dash_cv_have_attribute_alias" >&6; }
+if test "x$dash_cv_have_attribute_alias" = xyes; then
+
+$as_echo "#define HAVE_ALIAS_ATTRIBUTE 1" >>confdefs.h
+
+fi
+
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+  enableval=$enable_static;
+fi
+
+if test "$enable_static" = "yes"; then
+	export LDFLAGS="-static -Wl,--fatal-warnings"
+fi
+
+# Check whether --enable-fnmatch was given.
+if test "${enable_fnmatch+set}" = set; then :
+  enableval=$enable_fnmatch;
+fi
+
+# Check whether --enable-glob was given.
+if test "${enable_glob+set}" = set; then :
+  enableval=$enable_glob;
+fi
+
+
+
+for ac_header in alloca.h paths.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_fn_c_check_decl "$LINENO" "_PATH_BSHELL" "ac_cv_have_decl__PATH_BSHELL" "
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl__PATH_BSHELL" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define _PATH_BSHELL "/bin/sh"
+_ACEOF
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "_PATH_DEVNULL" "ac_cv_have_decl__PATH_DEVNULL" "
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl__PATH_DEVNULL" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define _PATH_DEVNULL "/dev/null"
+_ACEOF
+
+fi
+
+ac_fn_c_check_decl "$LINENO" "_PATH_TTY" "ac_cv_have_decl__PATH_TTY" "
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl__PATH_TTY" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define _PATH_TTY "/dev/tty"
+_ACEOF
+
+fi
+
+
+ac_fn_c_check_decl "$LINENO" "isblank" "ac_cv_have_decl_isblank" "#include <ctype.h>
+"
+if test "x$ac_cv_have_decl_isblank" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_ISBLANK $ac_have_decl
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of intmax_t" >&5
+$as_echo_n "checking size of intmax_t... " >&6; }
+if ${ac_cv_sizeof_intmax_t+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (intmax_t))" "ac_cv_sizeof_intmax_t"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_intmax_t" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (intmax_t)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_intmax_t=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_intmax_t" >&5
+$as_echo "$ac_cv_sizeof_intmax_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INTMAX_T $ac_cv_sizeof_intmax_t
+_ACEOF
+
+
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long int" >&5
+$as_echo_n "checking size of long long int... " >&6; }
+if ${ac_cv_sizeof_long_long_int+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long int))" "ac_cv_sizeof_long_long_int"        "$ac_includes_default"; then :
+
+else
+  if test "$ac_cv_type_long_long_int" = yes; then
+     { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (long long int)
+See \`config.log' for more details" "$LINENO" 5; }
+   else
+     ac_cv_sizeof_long_long_int=0
+   fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long_int" >&5
+$as_echo "$ac_cv_sizeof_long_long_int" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG_INT $ac_cv_sizeof_long_long_int
+_ACEOF
+
+
+
+if test "x$ac_cv_sizeof_intmax_t" = "x$ac_cv_sizeof_long_long_int"; then
+  intmax_fstr="lld"
+else
+  intmax_fstr="jd"
+fi
+
+ac_fn_c_check_decl "$LINENO" "PRIdMAX" "ac_cv_have_decl_PRIdMAX" "
+#include <inttypes.h>
+
+"
+if test "x$ac_cv_have_decl_PRIdMAX" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define PRIdMAX "$intmax_fstr"
+_ACEOF
+
+fi
+
+
+for ac_func in bsearch faccessat getpwnam getrlimit isalpha killpg \
+	       mempcpy \
+	       sigsetmask stpcpy strchrnul strsignal strtod strtoimax \
+	       strtoumax sysconf
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+# Check whether --enable-test-workaround was given.
+if test "${enable_test_workaround+set}" = set; then :
+  enableval=$enable_test_workaround;
+else
+  enable_test_workaround=auto
+fi
+
+
+if test "enable_test_workaround" = "auto" &&
+   test "$ac_cv_func_faccessat" = yes; then
+	case `uname -s 2>/dev/null` in
+	GNU/kFreeBSD | \
+	FreeBSD)
+		enable_test_workaround=yes
+	esac
+fi
+if test "$enable_test_workaround" = "yes"; then
+
+$as_echo "#define HAVE_TRADITIONAL_FACCESSAT 1" >>confdefs.h
+
+fi
+
+if test "$enable_fnmatch" = yes; then
+	use_fnmatch=
+	for ac_func in fnmatch
+do :
+  ac_fn_c_check_func "$LINENO" "fnmatch" "ac_cv_func_fnmatch"
+if test "x$ac_cv_func_fnmatch" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FNMATCH 1
+_ACEOF
+ use_fnmatch=yes
+fi
+done
+
+fi
+
+if test "$use_fnmatch" = yes && test "$enable_glob" = yes; then
+	for ac_func in glob
+do :
+  ac_fn_c_check_func "$LINENO" "glob" "ac_cv_func_glob"
+if test "x$ac_cv_func_glob" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GLOB 1
+_ACEOF
+
+fi
+done
+
+fi
+
+ac_fn_c_check_func "$LINENO" "signal" "ac_cv_func_signal"
+if test "x$ac_cv_func_signal" = xyes; then :
+
+fi
+
+if test "$ac_cv_func_signal" != yes; then
+	ac_fn_c_check_func "$LINENO" "bsd_signal" "ac_cv_func_bsd_signal"
+if test "x$ac_cv_func_bsd_signal" = xyes; then :
+
+$as_echo "#define signal bsd_signal" >>confdefs.h
+
+fi
+
+fi
+
+ac_fn_c_check_func "$LINENO" "stat64" "ac_cv_func_stat64"
+if test "x$ac_cv_func_stat64" = xyes; then :
+
+else
+
+
+$as_echo "#define fstat64 fstat" >>confdefs.h
+
+
+$as_echo "#define lstat64 lstat" >>confdefs.h
+
+
+$as_echo "#define stat64 stat" >>confdefs.h
+
+
+fi
+
+
+ac_fn_c_check_func "$LINENO" "open64" "ac_cv_func_open64"
+if test "x$ac_cv_func_open64" = xyes; then :
+
+else
+
+
+$as_echo "#define open64 open" >>confdefs.h
+
+
+$as_echo "#define readdir64 readdir" >>confdefs.h
+
+
+$as_echo "#define dirent64 dirent" >>confdefs.h
+
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stat::st_mtim" >&5
+$as_echo_n "checking for stat::st_mtim... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat foo; return sizeof(foo.st_mtim.tv_sec)
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  have_st_mtim=yes
+else
+  have_st_mtim=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_st_mtim" >&5
+$as_echo "$have_st_mtim" >&6; }
+if test "$have_st_mtim" = "yes"; then
+
+$as_echo "#define HAVE_ST_MTIM 1" >>confdefs.h
+
+fi
+
+
+# Check whether --with-libedit was given.
+if test "${with_libedit+set}" = set; then :
+  withval=$with_libedit;
+fi
+
+use_libedit=
+if test "$with_libedit" != "no"; then
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for history_init in -ledit" >&5
+$as_echo_n "checking for history_init in -ledit... " >&6; }
+if ${ac_cv_lib_edit_history_init+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ledit  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char history_init ();
+int
+main ()
+{
+return history_init ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_edit_history_init=yes
+else
+  ac_cv_lib_edit_history_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_history_init" >&5
+$as_echo "$ac_cv_lib_edit_history_init" >&6; }
+if test "x$ac_cv_lib_edit_history_init" = xyes; then :
+
+		ac_fn_c_check_header_mongrel "$LINENO" "histedit.h" "ac_cv_header_histedit_h" "$ac_includes_default"
+if test "x$ac_cv_header_histedit_h" = xyes; then :
+  use_libedit="yes"
+else
+  as_fn_error $? "Can't find required header files." "$LINENO" 5
+fi
+
+
+else
+
+		as_fn_error $? "Can't find libedit." "$LINENO" 5
+fi
+
+fi
+if test "$use_libedit" != "yes"; then
+
+$as_echo "#define SMALL 1" >>confdefs.h
+
+else
+	export LIBS="$LIBS -ledit"
+	for ac_func in _el_fn_sh_complete
+do :
+  ac_fn_c_check_func "$LINENO" "_el_fn_sh_complete" "ac_cv_func__el_fn_sh_complete"
+if test "x$ac_cv_func__el_fn_sh_complete" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE__EL_FN_SH_COMPLETE 1
+_ACEOF
+
+fi
+done
+
+fi
+# Check whether --enable-lineno was given.
+if test "${enable_lineno+set}" = set; then :
+  enableval=$enable_lineno;
+fi
+
+if test "$enable_lineno" != "no"; then
+
+$as_echo "#define WITH_LINENO 1" >>confdefs.h
+
+fi
+ac_config_files="$ac_config_files Makefile src/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+   if test -n "$am_sleep_pid"; then
+     # Hide warnings about reused PIDs.
+     wait $am_sleep_pid 2>/dev/null
+   fi
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by dash $as_me 0.5.11.2, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+dash config.status 0.5.11.2
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_tt"; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[	 ]*#[	 ]*define[	 ][	 ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[	 ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[	 ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+    } >"$ac_tmp/config.h" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$ac_tmp/config.h" "$ac_file" \
+	|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+      || as_fn_error $? "could not create -" "$LINENO" 5
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$_am_arg" : 'X\(//\)[^/]' \| \
+	 X"$_am_arg" : 'X\(//\)$' \| \
+	 X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Older Autoconf quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  # TODO: see whether this extra hack can be removed once we start
+  # requiring Autoconf 2.70 or later.
+  case $CONFIG_FILES in #(
+  *\'*) :
+    eval set x "$CONFIG_FILES" ;; #(
+  *) :
+    set x $CONFIG_FILES ;; #(
+  *) :
+     ;;
+esac
+  shift
+  # Used to flag and report bootstrapping failures.
+  am_rc=0
+  for am_mf
+  do
+    # Strip MF so we end up with the name of the file.
+    am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile which includes
+    # dependency-tracking related rules and includes.
+    # Grep'ing the whole file directly is not great: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+      || continue
+    am_dirpart=`$as_dirname -- "$am_mf" ||
+$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$am_mf" : 'X\(//\)[^/]' \| \
+	 X"$am_mf" : 'X\(//\)$' \| \
+	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$am_mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    am_filepart=`$as_basename -- "$am_mf" ||
+$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$am_mf" : 'X\(//\)$' \| \
+	 X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$am_mf" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+    { echo "$as_me:$LINENO: cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles" >&5
+   (cd "$am_dirpart" \
+      && sed -e '/# am--include-marker/d' "$am_filepart" \
+        | $MAKE -f - am--depfiles) >&5 2>&5
+   ac_status=$?
+   echo "$as_me:$LINENO: \$? = $ac_status" >&5
+   (exit $ac_status); } || am_rc=$?
+  done
+  if test $am_rc -ne 0; then
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Something went wrong bootstrapping makefile fragments
+    for automatic dependency tracking.  If GNU make was not used, consider
+    re-running the configure script with MAKE=\"gmake\" (or whatever is
+    necessary).  You can also try re-running configure with the
+    '--disable-dependency-tracking' option to at least be able to build
+    the package (albeit without support for automatic dependency tracking).
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+  { am_dirpart=; unset am_dirpart;}
+  { am_filepart=; unset am_filepart;}
+  { am_mf=; unset am_mf;}
+  { am_rc=; unset am_rc;}
+  rm -f conftest-deps.mk
+}
+ ;;
+
+  esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/bin/dash/configure.ac b/bin/dash/configure.ac
new file mode 100644
index 00000000..1edc45b8
--- /dev/null
+++ b/bin/dash/configure.ac
@@ -0,0 +1,194 @@
+AC_INIT([dash],[0.5.11.2])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
+AC_CONFIG_SRCDIR([src/main.c])
+
+AC_CONFIG_HEADERS(config.h)
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)])
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_USE_SYSTEM_EXTENSIONS
+
+AC_MSG_CHECKING([for build system compiler])
+if test "$cross_compiling" = yes; then
+	CC_FOR_BUILD=${CC_FOR_BUILD-cc}
+else
+	CC_FOR_BUILD=${CC}
+fi
+AC_MSG_RESULT(${CC_FOR_BUILD})
+AC_SUBST(CC_FOR_BUILD)
+
+AC_MSG_CHECKING([for __attribute__((__alias__()))])
+dash_cv_have_attribute_alias=no
+AC_LINK_IFELSE([AC_LANG_PROGRAM([void t() {}
+                                 void a() __attribute__((__alias__("t")));],
+                                [a();])],
+               [dash_cv_have_attribute_alias=yes])
+AC_MSG_RESULT($dash_cv_have_attribute_alias)
+if test "x$dash_cv_have_attribute_alias" = xyes; then
+  AC_DEFINE([HAVE_ALIAS_ATTRIBUTE], 1,
+            [Define if __attribute__((__alias__())) is supported])
+fi
+
+AC_ARG_ENABLE(static, AS_HELP_STRING(--enable-static, \
+				     [Build statical linked program]))
+if test "$enable_static" = "yes"; then
+	export LDFLAGS="-static -Wl,--fatal-warnings"
+fi
+
+AC_ARG_ENABLE(fnmatch, AS_HELP_STRING(--enable-fnmatch, \
+				      [Use fnmatch(3) from libc]))
+AC_ARG_ENABLE(glob, AS_HELP_STRING(--enable-glob, [Use glob(3) from libc]))
+
+dnl Checks for libraries.
+
+dnl Checks for header files.
+AC_CHECK_HEADERS(alloca.h paths.h)
+
+dnl Check for declarations
+AC_CHECK_DECL([_PATH_BSHELL],,AC_DEFINE_UNQUOTED([_PATH_BSHELL], "/bin/sh", [Define to system shell path]),[
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+])
+AC_CHECK_DECL([_PATH_DEVNULL],,AC_DEFINE_UNQUOTED([_PATH_DEVNULL], "/dev/null", [Define to devnull device node path]),[
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+])
+AC_CHECK_DECL([_PATH_TTY],,AC_DEFINE_UNQUOTED([_PATH_TTY], "/dev/tty", [Define to tty device node path]),[
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+])
+
+dnl Some systems lack isblank
+AC_CHECK_DECLS([isblank],,,[#include <ctype.h>])
+
+dnl Check for sizes of types
+AC_CHECK_SIZEOF([intmax_t])
+AC_CHECK_SIZEOF([long long int])
+
+dnl Select a fallback format string for intmax_t in case we don't find PRIdMAX
+if test "x$ac_cv_sizeof_intmax_t" = "x$ac_cv_sizeof_long_long_int"; then
+  intmax_fstr="lld"
+else
+  intmax_fstr="jd"
+fi
+
+dnl Check for PRIdMAX and define it to a fallback if not found
+AC_CHECK_DECL([PRIdMAX],,
+	[AC_DEFINE_UNQUOTED([PRIdMAX], "$intmax_fstr",
+				       [Define to printf format string for intmax_t])],
+        [
+#include <inttypes.h>
+])
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS(bsearch faccessat getpwnam getrlimit isalpha killpg \
+	       mempcpy \
+	       sigsetmask stpcpy strchrnul strsignal strtod strtoimax \
+	       strtoumax sysconf)
+
+dnl Check whether it's worth working around FreeBSD PR kern/125009.
+dnl The traditional behavior of access/faccessat is crazy, but
+dnl POSIX.1-2008 explicitly allows those functions to misbehave.
+dnl
+dnl Unaffected kernels:
+dnl
+dnl - all versions of Linux
+dnl - NetBSD sys/kern/vfs_subr.c 1.64, 1997-04-23
+dnl - FreeBSD 9 (r212002), 2010-09-10
+dnl - OpenBSD sys/kern/vfs_subr.c 1.166, 2008-06-09
+dnl
+dnl Also worked around in Debian's libc0.1 2.13-19 when using
+dnl kFreeBSD 8.
+
+AC_ARG_ENABLE(test-workaround, AS_HELP_STRING(--enable-test-workaround, \
+	[Guard against faccessat(2) that tells root all files are executable]),,
+	[enable_test_workaround=auto])
+
+if test "enable_test_workaround" = "auto" &&
+   test "$ac_cv_func_faccessat" = yes; then
+	case `uname -s 2>/dev/null` in
+	GNU/kFreeBSD | \
+	FreeBSD)
+		enable_test_workaround=yes
+	esac
+fi
+if test "$enable_test_workaround" = "yes"; then
+	AC_DEFINE([HAVE_TRADITIONAL_FACCESSAT], [1],
+		[Define if your faccessat tells root all files are executable])
+fi
+
+if test "$enable_fnmatch" = yes; then
+	use_fnmatch=
+	AC_CHECK_FUNCS(fnmatch, use_fnmatch=yes)
+fi
+
+if test "$use_fnmatch" = yes && test "$enable_glob" = yes; then
+	AC_CHECK_FUNCS(glob)
+fi
+
+dnl Check for klibc signal.
+AC_CHECK_FUNC(signal)
+if test "$ac_cv_func_signal" != yes; then
+	AC_CHECK_FUNC(bsd_signal,
+		      [AC_DEFINE(signal, bsd_signal,
+				 [klibc has bsd_signal instead of signal])])
+fi
+
+dnl Check for stat64 (dietlibc/klibc).
+AC_CHECK_FUNC(stat64,, [
+	AC_DEFINE(fstat64, fstat, [64-bit operations are the same as 32-bit])
+	AC_DEFINE(lstat64, lstat, [64-bit operations are the same as 32-bit])
+	AC_DEFINE(stat64, stat, [64-bit operations are the same as 32-bit])
+])
+
+dnl OS X apparently has stat64 but not open64.
+AC_CHECK_FUNC(open64,, [
+	AC_DEFINE(open64, open, [64-bit operations are the same as 32-bit])
+	AC_DEFINE(readdir64, readdir,
+		  [64-bit operations are the same as 32-bit])
+	AC_DEFINE(dirent64, dirent,
+		  [64-bit operations are the same as 32-bit])
+])
+
+dnl Check if struct stat has st_mtim.
+AC_MSG_CHECKING(for stat::st_mtim)
+AC_COMPILE_IFELSE(
+[AC_LANG_PROGRAM([#include <time.h>
+#include <sys/time.h>
+#include <sys/stat.h>],
+[struct stat foo; return sizeof(foo.st_mtim.tv_sec)])],
+have_st_mtim=yes, have_st_mtim=no)
+AC_MSG_RESULT($have_st_mtim)
+if test "$have_st_mtim" = "yes"; then
+	AC_DEFINE([HAVE_ST_MTIM], [1],
+		[Define if your `struct stat' has `st_mtim'])
+fi
+
+AC_ARG_WITH(libedit,
+	AS_HELP_STRING(--without-libedit, [Compile without libedit support]))
+use_libedit=
+if test "$with_libedit" != "no"; then
+	AC_CHECK_LIB(edit, history_init, [
+		AC_CHECK_HEADER([histedit.h], [use_libedit="yes"],
+				AC_MSG_ERROR(
+					[Can't find required header files.]))], [
+		AC_MSG_ERROR([Can't find libedit.])])
+fi
+if test "$use_libedit" != "yes"; then
+	AC_DEFINE([SMALL], 1, [Define if you build with -DSMALL])
+else
+	export LIBS="$LIBS -ledit"
+	AC_CHECK_FUNCS(_el_fn_sh_complete)
+fi
+AC_ARG_ENABLE(lineno, AS_HELP_STRING(--disable-lineno, \
+				     [Disable LINENO support]))
+if test "$enable_lineno" != "no"; then
+	AC_DEFINE([WITH_LINENO], 1, [Define if you build with -DWITH_LINENO])
+fi
+AC_CONFIG_FILES([Makefile src/Makefile])
+AC_OUTPUT
diff --git a/bin/dash/depcomp b/bin/dash/depcomp
new file mode 100755
index 00000000..6b391623
--- /dev/null
+++ b/bin/dash/depcomp
@@ -0,0 +1,791 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2020 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+    echo "$0: No command.  Try '$0 --help' for more information." 1>&2
+    exit 1;
+    ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputting dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'.  Note that this directory component will
+# be either empty or ending with a '/' character.  This is deliberate.
+set_dir_from ()
+{
+  case $1 in
+    */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+      *) dir=;;
+  esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+  base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+  echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+  # If the compiler actually managed to produce a dependency file,
+  # post-process it.
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form 'foo.o: dependency.h'.
+    # Do two passes, one to just change these to
+    #   $object: dependency.h
+    # and one to simply output
+    #   dependency.h:
+    # which is needed to avoid the deleted-header problem.
+    { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+      sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+    } > "$depfile"
+    rm -f "$tmpdepfile"
+  else
+    make_dummy_depfile
+  fi
+}
+
+# A tabulation character.
+tab='	'
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+  # This is just like dashmstdout with a different argument.
+  dashmflag=-xM
+  depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+  # This is just like msvisualcpp but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+  # This is just like msvc7 but w/o cygpath translation.
+  # Just convert the backslash-escaped backslashes to single forward
+  # slashes to satisfy depend.m4
+  cygpath_u='sed s,\\\\,/,g'
+  depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+  # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+  gccflag=-qmakedep=gcc,-MF
+  depmode=gcc
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).  Also, it might not be
+##   supported by the other compilers which use the 'gcc' depmode.
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The second -e expression handles DOS-style file names with drive
+  # letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the "deleted header file" problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+## Some versions of gcc put a space before the ':'.  On the theory
+## that the space means something, we add a space to the output as
+## well.  hp depmode also adds that space, but also prefixes the VPATH
+## to the object.  Take care to not repeat it in the output.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like '#:fec' to the end of the
+    # dependency line.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+      | tr "$nl" ' ' >> "$depfile"
+    echo >> "$depfile"
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' "$nl" < "$tmpdepfile" \
+      | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+      >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  set_dir_from "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  aix_post_process_depfile
+  ;;
+
+tcc)
+  # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+  # FIXME: That version still under development at the moment of writing.
+  #        Make that this statement remains true also for stable, released
+  #        versions.
+  # It will wrap lines (doesn't matter whether long or short) with a
+  # trailing '\', as in:
+  #
+  #   foo.o : \
+  #    foo.c \
+  #    foo.h \
+  #
+  # It will put a trailing '\' even on the last line, and will use leading
+  # spaces rather than leading tabs (at least since its commit 0394caf7
+  # "Emit spaces for -MD").
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+  # We have to change lines of the first kind to '$object: \'.
+  sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+  # And for each line of the second kind, we have to emit a 'dep.h:'
+  # dummy dependency, to avoid the deleted-header problem.
+  sed -n -e 's|^  *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file.  A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+  # Portland's C compiler understands '-MD'.
+  # Will always output deps to 'file.d' where file is the root name of the
+  # source file under compilation, even if file resides in a subdirectory.
+  # The object file name does not affect the name of the '.d' file.
+  # pgcc 10.2 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using '\' :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+  set_dir_from "$object"
+  # Use the source, not the object, to determine the base name, since
+  # that's sadly what pgcc will do too.
+  set_base_from "$source"
+  tmpdepfile=$base.d
+
+  # For projects that build the same source file twice into different object
+  # files, the pgcc approach of using the *source* file root name can cause
+  # problems in parallel builds.  Use a locking strategy to avoid stomping on
+  # the same $tmpdepfile.
+  lockdir=$base.d-lock
+  trap "
+    echo '$0: caught signal, cleaning up...' >&2
+    rmdir '$lockdir'
+    exit 1
+  " 1 2 13 15
+  numtries=100
+  i=$numtries
+  while test $i -gt 0; do
+    # mkdir is a portable test-and-set.
+    if mkdir "$lockdir" 2>/dev/null; then
+      # This process acquired the lock.
+      "$@" -MD
+      stat=$?
+      # Release the lock.
+      rmdir "$lockdir"
+      break
+    else
+      # If the lock is being held by a different process, wait
+      # until the winning process is done or we timeout.
+      while test -d "$lockdir" && test $i -gt 0; do
+        sleep 1
+        i=`expr $i - 1`
+      done
+    fi
+    i=`expr $i - 1`
+  done
+  trap - 1 2 13 15
+  if test $i -le 0; then
+    echo "$0: failed to acquire lock after $numtries attempts" >&2
+    echo "$0: check lockdir '$lockdir'" >&2
+    exit 1
+  fi
+
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  set_dir_from  "$object"
+  set_base_from "$object"
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -ne 0; then
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add 'dependent.h:' lines.
+    sed -ne '2,${
+               s/^ *//
+               s/ \\*$//
+               s/$/:/
+               p
+             }' "$tmpdepfile" >> "$depfile"
+  else
+    make_dummy_depfile
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+  # The Tru64 compiler uses -MD to generate dependencies as a side
+  # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+  # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+  # dependencies in 'foo.d' instead, so we check for that too.
+  # Subdirectories are respected.
+  set_dir_from  "$object"
+  set_base_from "$object"
+
+  if test "$libtool" = yes; then
+    # Libtool generates 2 separate objects for the 2 libraries.  These
+    # two compilations output dependencies in $dir.libs/$base.o.d and
+    # in $dir$base.o.d.  We have to check for both files, because
+    # one of the two compilations can be disabled.  We should prefer
+    # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+    # automatically cleaned when .libs/ is deleted, while ignoring
+    # the former would cause a distcleancheck panic.
+    tmpdepfile1=$dir$base.o.d          # libtool 1.5
+    tmpdepfile2=$dir.libs/$base.o.d    # Likewise.
+    tmpdepfile3=$dir.libs/$base.d      # Compaq CCC V6.2-504
+    "$@" -Wc,-MD
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    tmpdepfile3=$dir$base.d
+    "$@" -MD
+  fi
+
+  stat=$?
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  # Same post-processing that is required for AIX mode.
+  aix_post_process_depfile
+  ;;
+
+msvc7)
+  if test "$libtool" = yes; then
+    showIncludes=-Wc,-showIncludes
+  else
+    showIncludes=-showIncludes
+  fi
+  "$@" $showIncludes > "$tmpdepfile"
+  stat=$?
+  grep -v '^Note: including file: ' "$tmpdepfile"
+  if test $stat -ne 0; then
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  # The first sed program below extracts the file names and escapes
+  # backslashes for cygpath.  The second sed program outputs the file
+  # name when reading, but also accumulates all include files in the
+  # hold buffer in order to output them again at the end.  This only
+  # works with sed implementations that can handle large buffers.
+  sed < "$tmpdepfile" -n '
+/^Note: including file:  *\(.*\)/ {
+  s//\1/
+  s/\\/\\\\/g
+  p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+  s/.*/'"$tab"'/
+  G
+  p
+}' >> "$depfile"
+  echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+  rm -f "$tmpdepfile"
+  ;;
+
+msvc7msys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for ':'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
+  "$@" $dashmflag |
+    sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this sed invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  tr ' ' "$nl" < "$tmpdepfile" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  # makedepend may prepend the VPATH from the source file name to the object.
+  # No need to regex-escape $object, excess matching of '.' is harmless.
+  sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process the last invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed '1,2d' "$tmpdepfile" \
+    | tr ' ' "$nl" \
+    | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+    | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove '-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E \
+    | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+             -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+    | sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+        set fnord "$@"
+        shift
+        shift
+        ;;
+    *)
+        set fnord "$@" "$arg"
+        shift
+        shift
+        ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/bin/dash/install-sh b/bin/dash/install-sh
new file mode 100755
index 00000000..ec298b53
--- /dev/null
+++ b/bin/dash/install-sh
@@ -0,0 +1,541 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2020-11-14.01; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+tab='	'
+nl='
+'
+IFS=" $tab$nl"
+
+# Set DOITPROG to "echo" to test this script.
+
+doit=${DOITPROG-}
+doit_exec=${doit:-exec}
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+# Create dirs (including intermediate dirs) using mode 755.
+# This is like GNU 'install' as of coreutils 8.32 (2020).
+mkdir_umask=22
+
+backupsuffix=
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+is_target_a_directory=possibly
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -p            pass -p to $cpprog.
+  -s            $stripprog installed files.
+  -S SUFFIX     attempt to back up existing files, with suffix SUFFIX.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+
+By default, rm is invoked with -f; when overridden with RMPROG,
+it's up to you to specify -f if you want it.
+
+If -S is not specified, no backups are attempted.
+
+Email bug reports to bug-automake@gnu.org.
+Automake home page: https://www.gnu.org/software/automake/
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+        shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+        case $mode in
+          *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+            echo "$0: invalid mode: $mode" >&2
+            exit 1;;
+        esac
+        shift;;
+
+    -o) chowncmd="$chownprog $2"
+        shift;;
+
+    -p) cpprog="$cpprog -p";;
+
+    -s) stripcmd=$stripprog;;
+
+    -S) backupsuffix="$2"
+        shift;;
+
+    -t)
+        is_target_a_directory=always
+        dst_arg=$2
+        # Protect names problematic for 'test' and other utilities.
+        case $dst_arg in
+          -* | [=\(\)!]) dst_arg=./$dst_arg;;
+        esac
+        shift;;
+
+    -T) is_target_a_directory=never;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --) shift
+        break;;
+
+    -*) echo "$0: invalid option: $1" >&2
+        exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+  if test -n "$dst_arg"; then
+    echo "$0: target directory not allowed when installing a directory." >&2
+    exit 1
+  fi
+fi
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+    # Protect names problematic for 'test' and other utilities.
+    case $dst_arg in
+      -* | [=\(\)!]) dst_arg=./$dst_arg;;
+    esac
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call 'install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  if test $# -gt 1 || test "$is_target_a_directory" = always; then
+    if test ! -d "$dst_arg"; then
+      echo "$0: $dst_arg: Is not a directory." >&2
+      exit 1
+    fi
+  fi
+fi
+
+if test -z "$dir_arg"; then
+  do_exit='(exit $ret); exit $ret'
+  trap "ret=129; $do_exit" 1
+  trap "ret=130; $do_exit" 2
+  trap "ret=141; $do_exit" 13
+  trap "ret=143; $do_exit" 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+        u_plus_rw=
+      else
+        u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+        u_plus_rw=
+      else
+        u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names problematic for 'test' and other utilities.
+  case $src in
+    -* | [=\(\)!]) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+    # Don't chown directories that already exist.
+    if test $dstdir_status = 0; then
+      chowncmd=""
+    fi
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+    dst=$dst_arg
+
+    # If destination is a directory, append the input filename.
+    if test -d "$dst"; then
+      if test "$is_target_a_directory" = never; then
+        echo "$0: $dst_arg: Is a directory" >&2
+        exit 1
+      fi
+      dstdir=$dst
+      dstbase=`basename "$src"`
+      case $dst in
+	*/) dst=$dst$dstbase;;
+	*)  dst=$dst/$dstbase;;
+      esac
+      dstdir_status=0
+    else
+      dstdir=`dirname "$dst"`
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  case $dstdir in
+    */) dstdirslash=$dstdir;;
+    *)  dstdirslash=$dstdir/;;
+  esac
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+        # With -d, create the new directory with the user-specified mode.
+        # Otherwise, rely on $mkdir_umask.
+        if test -n "$dir_arg"; then
+          mkdir_mode=-m$mode
+        else
+          mkdir_mode=
+        fi
+
+        posix_mkdir=false
+	# The $RANDOM variable is not portable (e.g., dash).  Use it
+	# here however when possible just to lower collision chance.
+	tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+
+	trap '
+	  ret=$?
+	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
+	  exit $ret
+	' 0
+
+	# Because "mkdir -p" follows existing symlinks and we likely work
+	# directly in world-writeable /tmp, make sure that the '$tmpdir'
+	# directory is successfully created first before we actually test
+	# 'mkdir -p'.
+	if (umask $mkdir_umask &&
+	    $mkdirprog $mkdir_mode "$tmpdir" &&
+	    exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
+	then
+	  if test -z "$dir_arg" || {
+	       # Check for POSIX incompatibilities with -m.
+	       # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+	       # other-writable bit of parent directory when it shouldn't.
+	       # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+	       test_tmpdir="$tmpdir/a"
+	       ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+	       case $ls_ld_tmpdir in
+		 d????-?r-*) different_mode=700;;
+		 d????-?--*) different_mode=755;;
+		 *) false;;
+	       esac &&
+	       $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+		 ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+		 test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+	       }
+	     }
+	  then posix_mkdir=:
+	  fi
+	  rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+	else
+	  # Remove any dirs left behind by ancient mkdir implementations.
+	  rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
+	fi
+	trap '' 0;;
+    esac
+
+    if
+      $posix_mkdir && (
+        umask $mkdir_umask &&
+        $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+        /*) prefix='/';;
+        [-=\(\)!]*) prefix='./';;
+        *)  prefix='';;
+      esac
+
+      oIFS=$IFS
+      IFS=/
+      set -f
+      set fnord $dstdir
+      shift
+      set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+        test X"$d" = X && continue
+
+        prefix=$prefix$d
+        if test -d "$prefix"; then
+          prefixes=
+        else
+          if $posix_mkdir; then
+            (umask $mkdir_umask &&
+             $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+            # Don't fail if two instances are running concurrently.
+            test -d "$prefix" || exit 1
+          else
+            case $prefix in
+              *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+              *) qprefix=$prefix;;
+            esac
+            prefixes="$prefixes '$qprefix'"
+          fi
+        fi
+        prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+        # Don't fail if two instances are running concurrently.
+        (umask $mkdir_umask &&
+         eval "\$doit_exec \$mkdirprog $prefixes") ||
+          test -d "$dstdir" || exit 1
+        obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=${dstdirslash}_inst.$$_
+    rmtmp=${dstdirslash}_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask &&
+     { test -z "$stripcmd" || {
+	 # Create $dsttmp read-write so that cp doesn't create it read-only,
+	 # which would cause strip to fail.
+	 if test -z "$doit"; then
+	   : >"$dsttmp" # No need to fork-exec 'touch'.
+	 else
+	   $doit touch "$dsttmp"
+	 fi
+       }
+     } &&
+     $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"     2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp"  2>/dev/null` &&
+       set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       set +f &&
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # If $backupsuffix is set, and the file being installed
+      # already exists, attempt a backup.  Don't worry if it fails,
+      # e.g., if mv doesn't support -f.
+      if test -n "$backupsuffix" && test -f "$dst"; then
+        $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
+      fi
+
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+        # Now remove or move aside any old file at destination location.
+        # We try this two ways since rm can't unlink itself on some
+        # systems and the destination file might be busy for other
+        # reasons.  In this case, the final cleanup might fail but the new
+        # file should still install successfully.
+        {
+          test ! -f "$dst" ||
+          $doit $rmcmd "$dst" 2>/dev/null ||
+          { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+            { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
+          } ||
+          { echo "$0: cannot unlink or rename $dst" >&2
+            (exit 1); exit 1
+          }
+        } &&
+
+        # Now rename the file to the real destination.
+        $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/bin/dash/missing b/bin/dash/missing
new file mode 100755
index 00000000..8d0eaad2
--- /dev/null
+++ b/bin/dash/missing
@@ -0,0 +1,215 @@
+#! /bin/sh
+# Common wrapper for a few potentially missing GNU programs.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1996-2020 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try '$0 --help' for more information"
+  exit 1
+fi
+
+case $1 in
+
+  --is-lightweight)
+    # Used by our autoconf macros to check whether the available missing
+    # script is modern enough.
+    exit 0
+    ;;
+
+  --run)
+    # Back-compat with the calling convention used by older automake.
+    shift
+    ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal   autoconf  autoheader   autom4te  automake  makeinfo
+  bison     yacc      flex         lex       help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: unknown '$1' option"
+    echo 1>&2 "Try '$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch.  This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+  msg="probably too old"
+elif test $st -eq 127; then
+  # Program was missing.
+  msg="missing on your system"
+else
+  # Program was found and executed, but failed.  Give up.
+  exit $st
+fi
+
+perl_URL=https://www.perl.org/
+flex_URL=https://github.com/westes/flex
+gnu_software_URL=https://www.gnu.org/software
+
+program_details ()
+{
+  case $1 in
+    aclocal|automake)
+      echo "The '$1' program is part of the GNU Automake package:"
+      echo "<$gnu_software_URL/automake>"
+      echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/autoconf>"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+    autoconf|autom4te|autoheader)
+      echo "The '$1' program is part of the GNU Autoconf package:"
+      echo "<$gnu_software_URL/autoconf/>"
+      echo "It also requires GNU m4 and Perl in order to run:"
+      echo "<$gnu_software_URL/m4/>"
+      echo "<$perl_URL>"
+      ;;
+  esac
+}
+
+give_advice ()
+{
+  # Normalize program name to check for.
+  normalized_program=`echo "$1" | sed '
+    s/^gnu-//; t
+    s/^gnu//; t
+    s/^g//; t'`
+
+  printf '%s\n' "'$1' is $msg."
+
+  configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+  case $normalized_program in
+    autoconf*)
+      echo "You should only need it if you modified 'configure.ac',"
+      echo "or m4 files included by it."
+      program_details 'autoconf'
+      ;;
+    autoheader*)
+      echo "You should only need it if you modified 'acconfig.h' or"
+      echo "$configure_deps."
+      program_details 'autoheader'
+      ;;
+    automake*)
+      echo "You should only need it if you modified 'Makefile.am' or"
+      echo "$configure_deps."
+      program_details 'automake'
+      ;;
+    aclocal*)
+      echo "You should only need it if you modified 'acinclude.m4' or"
+      echo "$configure_deps."
+      program_details 'aclocal'
+      ;;
+   autom4te*)
+      echo "You might have modified some maintainer files that require"
+      echo "the 'autom4te' program to be rebuilt."
+      program_details 'autom4te'
+      ;;
+    bison*|yacc*)
+      echo "You should only need it if you modified a '.y' file."
+      echo "You may want to install the GNU Bison package:"
+      echo "<$gnu_software_URL/bison/>"
+      ;;
+    lex*|flex*)
+      echo "You should only need it if you modified a '.l' file."
+      echo "You may want to install the Fast Lexical Analyzer package:"
+      echo "<$flex_URL>"
+      ;;
+    help2man*)
+      echo "You should only need it if you modified a dependency" \
+           "of a man page."
+      echo "You may want to install the GNU Help2man package:"
+      echo "<$gnu_software_URL/help2man/>"
+    ;;
+    makeinfo*)
+      echo "You should only need it if you modified a '.texi' file, or"
+      echo "any other file indirectly affecting the aspect of the manual."
+      echo "You might want to install the Texinfo package:"
+      echo "<$gnu_software_URL/texinfo/>"
+      echo "The spurious makeinfo call might also be the consequence of"
+      echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+      echo "want to install GNU make:"
+      echo "<$gnu_software_URL/make/>"
+      ;;
+    *)
+      echo "You might have modified some files without having the proper"
+      echo "tools for further handling them.  Check the 'README' file, it"
+      echo "often tells you about the needed prerequisites for installing"
+      echo "this package.  You may also peek at any GNU archive site, in"
+      echo "case some other package contains this missing '$1' program."
+      ;;
+  esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+                       -e '2,$s/^/         /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/bin/dash/src/.gitignore b/bin/dash/src/.gitignore
new file mode 100644
index 00000000..644eccb8
--- /dev/null
+++ b/bin/dash/src/.gitignore
@@ -0,0 +1,13 @@
+*.o
+builtins.[ch]
+builtins.def
+dash
+init.c
+mkinit
+mknodes
+mksignames
+mksyntax
+nodes.[ch]
+signames.c
+syntax.[ch]
+token.h
diff --git a/bin/dash/src/Makefile.am b/bin/dash/src/Makefile.am
new file mode 100644
index 00000000..fb8229f1
--- /dev/null
+++ b/bin/dash/src/Makefile.am
@@ -0,0 +1,70 @@
+AM_YFLAGS = -d
+
+COMMON_CFLAGS = -Wall
+COMMON_CPPFLAGS = \
+	-DBSD=1 -DSHELL
+
+AM_CFLAGS = $(COMMON_CFLAGS)
+AM_CPPFLAGS = -include $(top_builddir)/config.h $(COMMON_CPPFLAGS)
+AM_CFLAGS_FOR_BUILD = -g -O2 $(COMMON_CFLAGS) 
+AM_CPPFLAGS_FOR_BUILD = $(COMMON_CPPFLAGS)
+
+COMPILE_FOR_BUILD = \
+	$(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(AM_CPPFLAGS_FOR_BUILD) \
+	$(CPPFLAGS_FOR_BUILD) \
+	$(AM_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) 
+
+bin_PROGRAMS = dash
+
+dash_CFILES = \
+	alias.c arith_yacc.c arith_yylex.c cd.c error.c eval.c exec.c expand.c \
+	histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
+	mystring.c options.c parser.c redir.c show.c trap.c output.c \
+	bltin/printf.c system.c bltin/test.c bltin/times.c var.c
+dash_SOURCES = \
+	$(dash_CFILES) \
+	alias.h arith_yacc.h bltin/bltin.h cd.h error.h eval.h exec.h \
+	expand.h \
+	init.h input.h jobs.h machdep.h mail.h main.h memalloc.h miscbltin.h \
+	myhistedit.h mystring.h options.h output.h parser.h redir.h shell.h \
+	show.h system.h trap.h var.h
+dash_LDADD = builtins.o init.o nodes.o signames.o syntax.o
+
+HELPERS = mkinit mksyntax mknodes mksignames
+
+BUILT_SOURCES = builtins.h nodes.h syntax.h token.h token_vars.h
+CLEANFILES = \
+	$(BUILT_SOURCES) $(dash_LDADD:%.o=%.c) \
+	$(HELPERS) builtins.def
+
+man_MANS = dash.1
+EXTRA_DIST = \
+	$(man_MANS) \
+	mktokens mkbuiltins builtins.def.in mkinit.c \
+	mknodes.c nodetypes nodes.c.pat mksyntax.c mksignames.c
+
+token.h token_vars.h: mktokens
+	$(AM_V_GEN)$(SHELL) mktokens
+
+builtins.def: builtins.def.in $(top_builddir)/config.h
+	$(AM_V_CC)$(COMPILE) -E -x c -o $@ builtins.def.in
+
+builtins.c builtins.h: mkbuiltins builtins.def
+	$(AM_V_GEN)$(SHELL) mkbuiltins builtins.def
+
+init.c: mkinit $(dash_CFILES)
+	$(AM_V_GEN)./mkinit $(dash_CFILES)
+
+nodes.c nodes.h: mknodes nodetypes nodes.c.pat
+	$(AM_V_GEN)./mknodes nodetypes nodes.c.pat
+
+syntax.c syntax.h: mksyntax
+	$(AM_V_GEN)./mksyntax
+
+signames.c: mksignames
+	$(AM_V_GEN)./mksignames
+
+mksyntax: token.h
+
+$(HELPERS):
+	$(AM_V_CC)$(COMPILE_FOR_BUILD) -o $@ $@.c
diff --git a/bin/dash/src/Makefile.in b/bin/dash/src/Makefile.in
new file mode 100644
index 00000000..ae25f565
--- /dev/null
+++ b/bin/dash/src/Makefile.in
@@ -0,0 +1,834 @@
+# Makefile.in generated by automake 1.16.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2020 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+  if test -z '$(MAKELEVEL)'; then \
+    false; \
+  elif test -n '$(MAKE_HOST)'; then \
+    true; \
+  elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+    true; \
+  else \
+    false; \
+  fi; \
+}
+am__make_running_with_option = \
+  case $${target_option-} in \
+      ?) ;; \
+      *) echo "am__make_running_with_option: internal error: invalid" \
+              "target option '$${target_option-}' specified" >&2; \
+         exit 1;; \
+  esac; \
+  has_opt=no; \
+  sane_makeflags=$$MAKEFLAGS; \
+  if $(am__is_gnu_make); then \
+    sane_makeflags=$$MFLAGS; \
+  else \
+    case $$MAKEFLAGS in \
+      *\\[\ \	]*) \
+        bs=\\; \
+        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
+    esac; \
+  fi; \
+  skip_next=no; \
+  strip_trailopt () \
+  { \
+    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+  }; \
+  for flg in $$sane_makeflags; do \
+    test $$skip_next = yes && { skip_next=no; continue; }; \
+    case $$flg in \
+      *=*|--*) continue;; \
+        -*I) strip_trailopt 'I'; skip_next=yes;; \
+      -*I?*) strip_trailopt 'I';; \
+        -*O) strip_trailopt 'O'; skip_next=yes;; \
+      -*O?*) strip_trailopt 'O';; \
+        -*l) strip_trailopt 'l'; skip_next=yes;; \
+      -*l?*) strip_trailopt 'l';; \
+      -[dEDm]) skip_next=yes;; \
+      -[JT]) skip_next=yes;; \
+    esac; \
+    case $$flg in \
+      *$$target_option*) has_opt=yes; break;; \
+    esac; \
+  done; \
+  test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+bin_PROGRAMS = dash$(EXEEXT)
+subdir = src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+	$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"
+PROGRAMS = $(bin_PROGRAMS)
+am__dirstamp = $(am__leading_dot)dirstamp
+am__objects_1 = alias.$(OBJEXT) arith_yacc.$(OBJEXT) \
+	arith_yylex.$(OBJEXT) cd.$(OBJEXT) error.$(OBJEXT) \
+	eval.$(OBJEXT) exec.$(OBJEXT) expand.$(OBJEXT) \
+	histedit.$(OBJEXT) input.$(OBJEXT) jobs.$(OBJEXT) \
+	mail.$(OBJEXT) main.$(OBJEXT) memalloc.$(OBJEXT) \
+	miscbltin.$(OBJEXT) mystring.$(OBJEXT) options.$(OBJEXT) \
+	parser.$(OBJEXT) redir.$(OBJEXT) show.$(OBJEXT) trap.$(OBJEXT) \
+	output.$(OBJEXT) bltin/printf.$(OBJEXT) system.$(OBJEXT) \
+	bltin/test.$(OBJEXT) bltin/times.$(OBJEXT) var.$(OBJEXT)
+am_dash_OBJECTS = $(am__objects_1)
+dash_OBJECTS = $(am_dash_OBJECTS)
+dash_DEPENDENCIES = builtins.o init.o nodes.o signames.o syntax.o
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo "  GEN     " $@;
+am__v_GEN_1 = 
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 = 
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/alias.Po ./$(DEPDIR)/arith_yacc.Po \
+	./$(DEPDIR)/arith_yylex.Po ./$(DEPDIR)/cd.Po \
+	./$(DEPDIR)/error.Po ./$(DEPDIR)/eval.Po ./$(DEPDIR)/exec.Po \
+	./$(DEPDIR)/expand.Po ./$(DEPDIR)/histedit.Po \
+	./$(DEPDIR)/input.Po ./$(DEPDIR)/jobs.Po ./$(DEPDIR)/mail.Po \
+	./$(DEPDIR)/main.Po ./$(DEPDIR)/memalloc.Po \
+	./$(DEPDIR)/miscbltin.Po ./$(DEPDIR)/mystring.Po \
+	./$(DEPDIR)/options.Po ./$(DEPDIR)/output.Po \
+	./$(DEPDIR)/parser.Po ./$(DEPDIR)/redir.Po ./$(DEPDIR)/show.Po \
+	./$(DEPDIR)/system.Po ./$(DEPDIR)/trap.Po ./$(DEPDIR)/var.Po \
+	bltin/$(DEPDIR)/printf.Po bltin/$(DEPDIR)/test.Po \
+	bltin/$(DEPDIR)/times.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo "  CC      " $@;
+am__v_CC_1 = 
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo "  CCLD    " $@;
+am__v_CCLD_1 = 
+SOURCES = $(dash_SOURCES)
+DIST_SOURCES = $(dash_SOURCES)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+  test -z "$$files" \
+    || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+    || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+         $(am__cd) "$$dir" && rm -f $$files; }; \
+  }
+man1dir = $(mandir)/man1
+NROFF = nroff
+MANS = $(man_MANS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates.  Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+  BEGIN { nonempty = 0; } \
+  { items[$$0] = 1; nonempty = 1; } \
+  END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique.  This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+  list='$(am__tagged_files)'; \
+  unique=`for i in $$list; do \
+    if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+  done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build_alias = @build_alias@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host_alias = @host_alias@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_YFLAGS = -d
+COMMON_CFLAGS = -Wall
+COMMON_CPPFLAGS = \
+	-DBSD=1 -DSHELL
+
+AM_CFLAGS = $(COMMON_CFLAGS)
+AM_CPPFLAGS = -include $(top_builddir)/config.h $(COMMON_CPPFLAGS)
+AM_CFLAGS_FOR_BUILD = -g -O2 $(COMMON_CFLAGS) 
+AM_CPPFLAGS_FOR_BUILD = $(COMMON_CPPFLAGS)
+COMPILE_FOR_BUILD = \
+	$(CC_FOR_BUILD) $(DEFAULT_INCLUDES) $(AM_CPPFLAGS_FOR_BUILD) \
+	$(CPPFLAGS_FOR_BUILD) \
+	$(AM_CFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD) 
+
+dash_CFILES = \
+	alias.c arith_yacc.c arith_yylex.c cd.c error.c eval.c exec.c expand.c \
+	histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \
+	mystring.c options.c parser.c redir.c show.c trap.c output.c \
+	bltin/printf.c system.c bltin/test.c bltin/times.c var.c
+
+dash_SOURCES = \
+	$(dash_CFILES) \
+	alias.h arith_yacc.h bltin/bltin.h cd.h error.h eval.h exec.h \
+	expand.h \
+	init.h input.h jobs.h machdep.h mail.h main.h memalloc.h miscbltin.h \
+	myhistedit.h mystring.h options.h output.h parser.h redir.h shell.h \
+	show.h system.h trap.h var.h
+
+dash_LDADD = builtins.o init.o nodes.o signames.o syntax.o
+HELPERS = mkinit mksyntax mknodes mksignames
+BUILT_SOURCES = builtins.h nodes.h syntax.h token.h token_vars.h
+CLEANFILES = \
+	$(BUILT_SOURCES) $(dash_LDADD:%.o=%.c) \
+	$(HELPERS) builtins.def
+
+man_MANS = dash.1
+EXTRA_DIST = \
+	$(man_MANS) \
+	mktokens mkbuiltins builtins.def.in mkinit.c \
+	mknodes.c nodetypes nodes.c.pat mksyntax.c mksignames.c
+
+all: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+	@for dep in $?; do \
+	  case '$(am__configure_deps)' in \
+	    *$$dep*) \
+	      ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+	        && { if test -f $@; then exit 0; else break; fi; }; \
+	      exit 1;; \
+	  esac; \
+	done; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/Makefile'; \
+	$(am__cd) $(top_srcdir) && \
+	  $(AUTOMAKE) --foreign src/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+	@case '$?' in \
+	  *config.status*) \
+	    cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+	  *) \
+	    echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+	    cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+	esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+	@$(NORMAL_INSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	if test -n "$$list"; then \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+	fi; \
+	for p in $$list; do echo "$$p $$p"; done | \
+	sed 's/$(EXEEXT)$$//' | \
+	while read p p1; do if test -f $$p \
+	  ; then echo "$$p"; echo "$$p"; else :; fi; \
+	done | \
+	sed -e 'p;s,.*/,,;n;h' \
+	    -e 's|.*|.|' \
+	    -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+	sed 'N;N;N;s,\n, ,g' | \
+	$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+	  { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+	    if ($$2 == $$4) files[d] = files[d] " " $$1; \
+	    else { print "f", $$3 "/" $$4, $$1; } } \
+	  END { for (d in files) print "f", d, files[d] }' | \
+	while read type dir files; do \
+	    if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+	    test -z "$$files" || { \
+	      echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+	      $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+	    } \
+	; done
+
+uninstall-binPROGRAMS:
+	@$(NORMAL_UNINSTALL)
+	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+	files=`for p in $$list; do echo "$$p"; done | \
+	  sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+	      -e 's/$$/$(EXEEXT)/' \
+	`; \
+	test -n "$$list" || exit 0; \
+	echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+	cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+	-test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+bltin/$(am__dirstamp):
+	@$(MKDIR_P) bltin
+	@: > bltin/$(am__dirstamp)
+bltin/$(DEPDIR)/$(am__dirstamp):
+	@$(MKDIR_P) bltin/$(DEPDIR)
+	@: > bltin/$(DEPDIR)/$(am__dirstamp)
+bltin/printf.$(OBJEXT): bltin/$(am__dirstamp) \
+	bltin/$(DEPDIR)/$(am__dirstamp)
+bltin/test.$(OBJEXT): bltin/$(am__dirstamp) \
+	bltin/$(DEPDIR)/$(am__dirstamp)
+bltin/times.$(OBJEXT): bltin/$(am__dirstamp) \
+	bltin/$(DEPDIR)/$(am__dirstamp)
+
+dash$(EXEEXT): $(dash_OBJECTS) $(dash_DEPENDENCIES) $(EXTRA_dash_DEPENDENCIES) 
+	@rm -f dash$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(dash_OBJECTS) $(dash_LDADD) $(LIBS)
+
+mostlyclean-compile:
+	-rm -f *.$(OBJEXT)
+	-rm -f bltin/*.$(OBJEXT)
+
+distclean-compile:
+	-rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alias.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arith_yacc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arith_yylex.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/error.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eval.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expand.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/histedit.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/input.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jobs.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mail.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalloc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/miscbltin.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mystring.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/options.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/output.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parser.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/redir.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/show.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/system.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/var.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@bltin/$(DEPDIR)/printf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@bltin/$(DEPDIR)/test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@bltin/$(DEPDIR)/times.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+	@$(MKDIR_P) $(@D)
+	@echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+install-man1: $(man_MANS)
+	@$(NORMAL_INSTALL)
+	@list1=''; \
+	list2='$(man_MANS)'; \
+	test -n "$(man1dir)" \
+	  && test -n "`echo $$list1$$list2`" \
+	  || exit 0; \
+	echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
+	$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
+	{ for i in $$list1; do echo "$$i"; done;  \
+	if test -n "$$list2"; then \
+	  for i in $$list2; do echo "$$i"; done \
+	    | sed -n '/\.1[a-z]*$$/p'; \
+	fi; \
+	} | while read p; do \
+	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+	  echo "$$d$$p"; echo "$$p"; \
+	done | \
+	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
+	sed 'N;N;s,\n, ,g' | { \
+	list=; while read file base inst; do \
+	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
+	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
+	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
+	  fi; \
+	done; \
+	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
+	while read files; do \
+	  test -z "$$files" || { \
+	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
+	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
+	done; }
+
+uninstall-man1:
+	@$(NORMAL_UNINSTALL)
+	@list=''; test -n "$(man1dir)" || exit 0; \
+	files=`{ for i in $$list; do echo "$$i"; done; \
+	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
+	  sed -n '/\.1[a-z]*$$/p'; \
+	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
+	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
+	dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+	$(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	set x; \
+	here=`pwd`; \
+	$(am__define_uniq_tagged_files); \
+	shift; \
+	if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+	  test -n "$$unique" || unique=$$empty_fix; \
+	  if test $$# -gt 0; then \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      "$$@" $$unique; \
+	  else \
+	    $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+	      $$unique; \
+	  fi; \
+	fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+	$(am__define_uniq_tagged_files); \
+	test -z "$(CTAGS_ARGS)$$unique" \
+	  || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+	     $$unique
+
+GTAGS:
+	here=`$(am__cd) $(top_builddir) && pwd` \
+	  && $(am__cd) $(top_srcdir) \
+	  && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+	list='$(am__tagged_files)'; \
+	case "$(srcdir)" in \
+	  [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+	  *) sdir=$(subdir)/$(srcdir) ;; \
+	esac; \
+	for i in $$list; do \
+	  if test -f "$$i"; then \
+	    echo "$(subdir)/$$i"; \
+	  else \
+	    echo "$$sdir/$$i"; \
+	  fi; \
+	done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+	@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+	list='$(DISTFILES)'; \
+	  dist_files=`for file in $$list; do echo $$file; done | \
+	  sed -e "s|^$$srcdirstrip/||;t" \
+	      -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+	case $$dist_files in \
+	  */*) $(MKDIR_P) `echo "$$dist_files" | \
+			   sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+			   sort -u` ;; \
+	esac; \
+	for file in $$dist_files; do \
+	  if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+	  if test -d $$d/$$file; then \
+	    dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+	    if test -d "$(distdir)/$$file"; then \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+	      cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+	      find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+	    fi; \
+	    cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+	  else \
+	    test -f "$(distdir)/$$file" \
+	    || cp -p $$d/$$file "$(distdir)/$$file" \
+	    || exit 1; \
+	  fi; \
+	done
+check-am: all-am
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+installdirs:
+	for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \
+	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+	done
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+	@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+	if test -z '$(STRIP)'; then \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	      install; \
+	else \
+	  $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+	    install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+	    "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+	fi
+mostlyclean-generic:
+
+clean-generic:
+	-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+	-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+	-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+	-rm -f bltin/$(DEPDIR)/$(am__dirstamp)
+	-rm -f bltin/$(am__dirstamp)
+
+maintainer-clean-generic:
+	@echo "This command is intended for maintainers to use"
+	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+		-rm -f ./$(DEPDIR)/alias.Po
+	-rm -f ./$(DEPDIR)/arith_yacc.Po
+	-rm -f ./$(DEPDIR)/arith_yylex.Po
+	-rm -f ./$(DEPDIR)/cd.Po
+	-rm -f ./$(DEPDIR)/error.Po
+	-rm -f ./$(DEPDIR)/eval.Po
+	-rm -f ./$(DEPDIR)/exec.Po
+	-rm -f ./$(DEPDIR)/expand.Po
+	-rm -f ./$(DEPDIR)/histedit.Po
+	-rm -f ./$(DEPDIR)/input.Po
+	-rm -f ./$(DEPDIR)/jobs.Po
+	-rm -f ./$(DEPDIR)/mail.Po
+	-rm -f ./$(DEPDIR)/main.Po
+	-rm -f ./$(DEPDIR)/memalloc.Po
+	-rm -f ./$(DEPDIR)/miscbltin.Po
+	-rm -f ./$(DEPDIR)/mystring.Po
+	-rm -f ./$(DEPDIR)/options.Po
+	-rm -f ./$(DEPDIR)/output.Po
+	-rm -f ./$(DEPDIR)/parser.Po
+	-rm -f ./$(DEPDIR)/redir.Po
+	-rm -f ./$(DEPDIR)/show.Po
+	-rm -f ./$(DEPDIR)/system.Po
+	-rm -f ./$(DEPDIR)/trap.Po
+	-rm -f ./$(DEPDIR)/var.Po
+	-rm -f bltin/$(DEPDIR)/printf.Po
+	-rm -f bltin/$(DEPDIR)/test.Po
+	-rm -f bltin/$(DEPDIR)/times.Po
+	-rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+	distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man: install-man1
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+		-rm -f ./$(DEPDIR)/alias.Po
+	-rm -f ./$(DEPDIR)/arith_yacc.Po
+	-rm -f ./$(DEPDIR)/arith_yylex.Po
+	-rm -f ./$(DEPDIR)/cd.Po
+	-rm -f ./$(DEPDIR)/error.Po
+	-rm -f ./$(DEPDIR)/eval.Po
+	-rm -f ./$(DEPDIR)/exec.Po
+	-rm -f ./$(DEPDIR)/expand.Po
+	-rm -f ./$(DEPDIR)/histedit.Po
+	-rm -f ./$(DEPDIR)/input.Po
+	-rm -f ./$(DEPDIR)/jobs.Po
+	-rm -f ./$(DEPDIR)/mail.Po
+	-rm -f ./$(DEPDIR)/main.Po
+	-rm -f ./$(DEPDIR)/memalloc.Po
+	-rm -f ./$(DEPDIR)/miscbltin.Po
+	-rm -f ./$(DEPDIR)/mystring.Po
+	-rm -f ./$(DEPDIR)/options.Po
+	-rm -f ./$(DEPDIR)/output.Po
+	-rm -f ./$(DEPDIR)/parser.Po
+	-rm -f ./$(DEPDIR)/redir.Po
+	-rm -f ./$(DEPDIR)/show.Po
+	-rm -f ./$(DEPDIR)/system.Po
+	-rm -f ./$(DEPDIR)/trap.Po
+	-rm -f ./$(DEPDIR)/var.Po
+	-rm -f bltin/$(DEPDIR)/printf.Po
+	-rm -f bltin/$(DEPDIR)/test.Po
+	-rm -f bltin/$(DEPDIR)/times.Po
+	-rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+
+uninstall-man: uninstall-man1
+
+.MAKE: all check install install-am install-exec install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+	clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \
+	distclean distclean-compile distclean-generic distclean-tags \
+	distdir dvi dvi-am html html-am info info-am install \
+	install-am install-binPROGRAMS install-data install-data-am \
+	install-dvi install-dvi-am install-exec install-exec-am \
+	install-html install-html-am install-info install-info-am \
+	install-man install-man1 install-pdf install-pdf-am install-ps \
+	install-ps-am install-strip installcheck installcheck-am \
+	installdirs maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \
+	ps ps-am tags tags-am uninstall uninstall-am \
+	uninstall-binPROGRAMS uninstall-man uninstall-man1
+
+.PRECIOUS: Makefile
+
+
+token.h token_vars.h: mktokens
+	$(AM_V_GEN)$(SHELL) mktokens
+
+builtins.def: builtins.def.in $(top_builddir)/config.h
+	$(AM_V_CC)$(COMPILE) -E -x c -o $@ builtins.def.in
+
+builtins.c builtins.h: mkbuiltins builtins.def
+	$(AM_V_GEN)$(SHELL) mkbuiltins builtins.def
+
+init.c: mkinit $(dash_CFILES)
+	$(AM_V_GEN)./mkinit $(dash_CFILES)
+
+nodes.c nodes.h: mknodes nodetypes nodes.c.pat
+	$(AM_V_GEN)./mknodes nodetypes nodes.c.pat
+
+syntax.c syntax.h: mksyntax
+	$(AM_V_GEN)./mksyntax
+
+signames.c: mksignames
+	$(AM_V_GEN)./mksignames
+
+mksyntax: token.h
+
+$(HELPERS):
+	$(AM_V_CC)$(COMPILE_FOR_BUILD) -o $@ $@.c
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/bin/dash/src/TOUR b/bin/dash/src/TOUR
new file mode 100644
index 00000000..e30836e1
--- /dev/null
+++ b/bin/dash/src/TOUR
@@ -0,0 +1,343 @@
+#	@(#)TOUR	8.1 (Berkeley) 5/31/93
+
+NOTE -- This is the original TOUR paper distributed with ash and
+does not represent the current state of the shell.  It is provided anyway
+since it provides helpful information for how the shell is structured,
+but be warned that things have changed -- the current shell is
+still under development.
+
+================================================================
+
+                       A Tour through Ash
+
+               Copyright 1989 by Kenneth Almquist.
+
+
+DIRECTORIES:  The subdirectory bltin contains commands which can
+be compiled stand-alone.  The rest of the source is in the main
+ash directory.
+
+SOURCE CODE GENERATORS:  Files whose names begin with "mk" are
+programs that generate source code.  A complete list of these
+programs is:
+
+        program         intput files        generates
+        -------         ------------        ---------
+        mkbuiltins      builtins            builtins.h builtins.c
+        mkinit          *.c                 init.c
+        mknodes         nodetypes           nodes.h nodes.c
+        mksignames          -               signames.h signames.c
+        mksyntax            -               syntax.h syntax.c
+        mktokens            -               token.h
+        bltin/mkexpr    unary_op binary_op  operators.h operators.c
+
+There are undoubtedly too many of these.  Mkinit searches all the
+C source files for entries looking like:
+
+        INIT {
+              x = 1;    /* executed during initialization */
+        }
+
+        RESET {
+              x = 2;    /* executed when the shell does a longjmp
+                           back to the main command loop */
+        }
+
+It pulls this code out into routines which are when particular
+events occur.  The intent is to improve modularity by isolating
+the information about which modules need to be explicitly
+initialized/reset within the modules themselves.
+
+Mkinit recognizes several constructs for placing declarations in
+the init.c file.
+        INCLUDE "file.h"
+includes a file.  The storage class MKINIT makes a declaration
+available in the init.c file, for example:
+        MKINIT int funcnest;    /* depth of function calls */
+MKINIT alone on a line introduces a structure or union declara-
+tion:
+        MKINIT
+        struct redirtab {
+              short renamed[10];
+        };
+Preprocessor #define statements are copied to init.c without any
+special action to request this.
+
+INDENTATION:  The ash source is indented in multiples of six
+spaces.  The only study that I have heard of on the subject con-
+cluded that the optimal amount to indent is in the range of four
+to six spaces.  I use six spaces since it is not too big a jump
+from the widely used eight spaces.  If you really hate six space
+indentation, use the adjind (source included) program to change
+it to something else.
+
+EXCEPTIONS:  Code for dealing with exceptions appears in
+exceptions.c.  The C language doesn't include exception handling,
+so I implement it using setjmp and longjmp.  The global variable
+exception contains the type of exception.  EXERROR is raised by
+calling error.  EXINT is an interrupt.
+
+INTERRUPTS:  In an interactive shell, an interrupt will cause an
+EXINT exception to return to the main command loop.  (Exception:
+EXINT is not raised if the user traps interrupts using the trap
+command.)  The INTOFF and INTON macros (defined in exception.h)
+provide uninterruptable critical sections.  Between the execution
+of INTOFF and the execution of INTON, interrupt signals will be
+held for later delivery.  INTOFF and INTON can be nested.
+
+MEMALLOC.C:  Memalloc.c defines versions of malloc and realloc
+which call error when there is no memory left.  It also defines a
+stack oriented memory allocation scheme.  Allocating off a stack
+is probably more efficient than allocation using malloc, but the
+big advantage is that when an exception occurs all we have to do
+to free up the memory in use at the time of the exception is to
+restore the stack pointer.  The stack is implemented using a
+linked list of blocks.
+
+STPUTC:  If the stack were contiguous, it would be easy to store
+strings on the stack without knowing in advance how long the
+string was going to be:
+        p = stackptr;
+        *p++ = c;       /* repeated as many times as needed */
+        stackptr = p;
+The following three macros (defined in memalloc.h) perform these
+operations, but grow the stack if you run off the end:
+        STARTSTACKSTR(p);
+        STPUTC(c, p);   /* repeated as many times as needed */
+        grabstackstr(p);
+
+We now start a top-down look at the code:
+
+MAIN.C:  The main routine performs some initialization, executes
+the user's profile if necessary, and calls cmdloop.  Cmdloop is
+repeatedly parses and executes commands.
+
+OPTIONS.C:  This file contains the option processing code.  It is
+called from main to parse the shell arguments when the shell is
+invoked, and it also contains the set builtin.  The -i and -j op-
+tions (the latter turns on job control) require changes in signal
+handling.  The routines setjobctl (in jobs.c) and setinteractive
+(in trap.c) are called to handle changes to these options.
+
+PARSING:  The parser code is all in parser.c.  A recursive des-
+cent parser is used.  Syntax tables (generated by mksyntax) are
+used to classify characters during lexical analysis.  There are
+three tables:  one for normal use, one for use when inside single
+quotes, and one for use when inside double quotes.  The tables
+are machine dependent because they are indexed by character vari-
+ables and the range of a char varies from machine to machine.
+
+PARSE OUTPUT:  The output of the parser consists of a tree of
+nodes.  The various types of nodes are defined in the file node-
+types.
+
+Nodes of type NARG are used to represent both words and the con-
+tents of here documents.  An early version of ash kept the con-
+tents of here documents in temporary files, but keeping here do-
+cuments in memory typically results in significantly better per-
+formance.  It would have been nice to make it an option to use
+temporary files for here documents, for the benefit of small
+machines, but the code to keep track of when to delete the tem-
+porary files was complex and I never fixed all the bugs in it.
+(AT&T has been maintaining the Bourne shell for more than ten
+years, and to the best of my knowledge they still haven't gotten
+it to handle temporary files correctly in obscure cases.)
+
+The text field of a NARG structure points to the text of the
+word.  The text consists of ordinary characters and a number of
+special codes defined in parser.h.  The special codes are:
+
+        CTLVAR              Variable substitution
+        CTLENDVAR           End of variable substitution
+        CTLBACKQ            Command substitution
+        CTLESC              Escape next character
+
+A variable substitution contains the following elements:
+
+        CTLVAR type name '=' [ alternative-text CTLENDVAR ]
+
+The type field is a single character specifying the type of sub-
+stitution.  The possible types are:
+
+        VSNORMAL            $var
+        VSMINUS             ${var-text}
+        VSMINUS|VSNUL       ${var:-text}
+        VSPLUS              ${var+text}
+        VSPLUS|VSNUL        ${var:+text}
+        VSQUESTION          ${var?text}
+        VSQUESTION|VSNUL    ${var:?text}
+        VSASSIGN            ${var=text}
+        VSASSIGN|VSNUL      ${var=text}
+
+The name of the variable comes next, terminated by an equals
+sign.  If the type is not VSNORMAL, then the text field in the
+substitution follows, terminated by a CTLENDVAR byte.
+
+Commands in back quotes are parsed and stored in a linked list.
+The locations of these commands in the string are indicated by
+the CTLBACKQ character.
+
+The character CTLESC escapes the next character, so that in case
+any of the CTL characters mentioned above appear in the input,
+they can be passed through transparently.  CTLESC is also used to
+escape '*', '?', '[', and '!' characters which were quoted by the
+user and thus should not be used for file name generation.
+
+CTLESC characters have proved to be particularly tricky to get
+right.  In the case of here documents which are not subject to
+variable and command substitution, the parser doesn't insert any
+CTLESC characters to begin with (so the contents of the text
+field can be written without any processing).  Other here docu-
+ments, and words which are not subject to splitting and file name
+generation, have the CTLESC characters removed during the vari-
+able and command substitution phase.  Words which are subject
+splitting and file name generation have the CTLESC characters re-
+moved as part of the file name phase.
+
+EXECUTION:  Command execution is handled by the following files:
+        eval.c     The top level routines.
+        redir.c    Code to handle redirection of input and output.
+        jobs.c     Code to handle forking, waiting, and job control.
+        exec.c     Code to path searches and the actual exec sys call.
+        expand.c   Code to evaluate arguments.
+        var.c      Maintains the variable symbol table.  Called from expand.c.
+
+EVAL.C:  Evaltree recursively executes a parse tree.  The exit
+status is returned in the global variable exitstatus.  The alter-
+native entry evalbackcmd is called to evaluate commands in back
+quotes.  It saves the result in memory if the command is a buil-
+tin; otherwise it forks off a child to execute the command and
+connects the standard output of the child to a pipe.
+
+JOBS.C:  To create a process, you call makejob to return a job
+structure, and then call forkshell (passing the job structure as
+an argument) to create the process.  Waitforjob waits for a job
+to complete.  These routines take care of process groups if job
+control is defined.
+
+REDIR.C:  Ash allows file descriptors to be redirected and then
+restored without forking off a child process.  This is accom-
+plished by duplicating the original file descriptors.  The redir-
+tab structure records where the file descriptors have be dupli-
+cated to.
+
+EXEC.C:  The routine find_command locates a command, and enters
+the command in the hash table if it is not already there.  The
+third argument specifies whether it is to print an error message
+if the command is not found.  (When a pipeline is set up,
+find_command is called for all the commands in the pipeline be-
+fore any forking is done, so to get the commands into the hash
+table of the parent process.  But to make command hashing as
+transparent as possible, we silently ignore errors at that point
+and only print error messages if the command cannot be found
+later.)
+
+The routine shellexec is the interface to the exec system call.
+
+EXPAND.C:  Arguments are processed in three passes.  The first
+(performed by the routine argstr) performs variable and command
+substitution.  The second (ifsbreakup) performs word splitting
+and the third (expandmeta) performs file name generation.  If the
+"/u" directory is simulated, then when "/u/username" is replaced
+by the user's home directory, the flag "didudir" is set.  This
+tells the cd command that it should print out the directory name,
+just as it would if the "/u" directory were implemented using
+symbolic links.
+
+VAR.C:  Variables are stored in a hash table.  Probably we should
+switch to extensible hashing.  The variable name is stored in the
+same string as the value (using the format "name=value") so that
+no string copying is needed to create the environment of a com-
+mand.  Variables which the shell references internally are preal-
+located so that the shell can reference the values of these vari-
+ables without doing a lookup.
+
+When a program is run, the code in eval.c sticks any environment
+variables which precede the command (as in "PATH=xxx command") in
+the variable table as the simplest way to strip duplicates, and
+then calls "environment" to get the value of the environment.
+There are two consequences of this.  First, if an assignment to
+PATH precedes the command, the value of PATH before the assign-
+ment must be remembered and passed to shellexec.  Second, if the
+program turns out to be a shell procedure, the strings from the
+environment variables which preceded the command must be pulled
+out of the table and replaced with strings obtained from malloc,
+since the former will automatically be freed when the stack (see
+the entry on memalloc.c) is emptied.
+
+BUILTIN COMMANDS:  The procedures for handling these are scat-
+tered throughout the code, depending on which location appears
+most appropriate.  They can be recognized because their names al-
+ways end in "cmd".  The mapping from names to procedures is
+specified in the file builtins, which is processed by the mkbuil-
+tins command.
+
+A builtin command is invoked with argc and argv set up like a
+normal program.  A builtin command is allowed to overwrite its
+arguments.  Builtin routines can call nextopt to do option pars-
+ing.  This is kind of like getopt, but you don't pass argc and
+argv to it.  Builtin routines can also call error.  This routine
+normally terminates the shell (or returns to the main command
+loop if the shell is interactive), but when called from a builtin
+command it causes the builtin command to terminate with an exit
+status of 2.
+
+The directory bltins contains commands which can be compiled in-
+dependently but can also be built into the shell for efficiency
+reasons.  The makefile in this directory compiles these programs
+in the normal fashion (so that they can be run regardless of
+whether the invoker is ash), but also creates a library named
+bltinlib.a which can be linked with ash.  The header file bltin.h
+takes care of most of the differences between the ash and the
+stand-alone environment.  The user should call the main routine
+"main", and #define main to be the name of the routine to use
+when the program is linked into ash.  This #define should appear
+before bltin.h is included; bltin.h will #undef main if the pro-
+gram is to be compiled stand-alone.
+
+CD.C:  This file defines the cd and pwd builtins.  The pwd com-
+mand runs /bin/pwd the first time it is invoked (unless the user
+has already done a cd to an absolute pathname), but then
+remembers the current directory and updates it when the cd com-
+mand is run, so subsequent pwd commands run very fast.  The main
+complication in the cd command is in the docd command, which
+resolves symbolic links into actual names and informs the user
+where the user ended up if he crossed a symbolic link.
+
+SIGNALS:  Trap.c implements the trap command.  The routine set-
+signal figures out what action should be taken when a signal is
+received and invokes the signal system call to set the signal ac-
+tion appropriately.  When a signal that a user has set a trap for
+is caught, the routine "onsig" sets a flag.  The routine dotrap
+is called at appropriate points to actually handle the signal.
+When an interrupt is caught and no trap has been set for that
+signal, the routine "onint" in error.c is called.
+
+OUTPUT:  Ash uses it's own output routines.  There are three out-
+put structures allocated.  "Output" represents the standard out-
+put, "errout" the standard error, and "memout" contains output
+which is to be stored in memory.  This last is used when a buil-
+tin command appears in backquotes, to allow its output to be col-
+lected without doing any I/O through the UNIX operating system.
+The variables out1 and out2 normally point to output and errout,
+respectively, but they are set to point to memout when appropri-
+ate inside backquotes.
+
+INPUT:  The basic input routine is pgetc, which reads from the
+current input file.  There is a stack of input files; the current
+input file is the top file on this stack.  The code allows the
+input to come from a string rather than a file.  (This is for the
+-c option and the "." and eval builtin commands.)  The global
+variable plinno is saved and restored when files are pushed and
+popped from the stack.  The parser routines store the number of
+the current line in this variable.
+
+DEBUGGING:  If DEBUG is defined in shell.h, then the shell will
+write debugging information to the file $HOME/trace.  Most of
+this is done using the TRACE macro, which takes a set of printf
+arguments inside two sets of parenthesis.  Example:
+"TRACE(("n=%d0, n))".  The double parenthesis are necessary be-
+cause the preprocessor can't handle functions with a variable
+number of arguments.  Defining DEBUG also causes the shell to
+generate a core dump if it is sent a quit signal.  The tracing
+code is in show.c.
diff --git a/bin/dash/src/alias.c b/bin/dash/src/alias.c
new file mode 100644
index 00000000..daeacbb8
--- /dev/null
+++ b/bin/dash/src/alias.c
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <stdlib.h>
+#include "shell.h"
+#include "input.h"
+#include "output.h"
+#include "error.h"
+#include "memalloc.h"
+#include "mystring.h"
+#include "alias.h"
+#include "options.h"	/* XXX for argptr (should remove?) */
+
+#define ATABSIZE 39
+
+struct alias *atab[ATABSIZE];
+
+STATIC void setalias(const char *, const char *);
+STATIC struct alias *freealias(struct alias *);
+STATIC struct alias **__lookupalias(const char *);
+
+STATIC
+void
+setalias(const char *name, const char *val)
+{
+	struct alias *ap, **app;
+
+	app = __lookupalias(name);
+	ap = *app;
+	INTOFF;
+	if (ap) {
+		if (!(ap->flag & ALIASINUSE)) {
+			ckfree(ap->val);
+		}
+		ap->val	= savestr(val);
+		ap->flag &= ~ALIASDEAD;
+	} else {
+		/* not found */
+		ap = ckmalloc(sizeof (struct alias));
+		ap->name = savestr(name);
+		ap->val = savestr(val);
+		ap->flag = 0;
+		ap->next = 0;
+		*app = ap;
+	}
+	INTON;
+}
+
+int
+unalias(const char *name)
+{
+	struct alias **app;
+
+	app = __lookupalias(name);
+
+	if (*app) {
+		INTOFF;
+		*app = freealias(*app);
+		INTON;
+		return (0);
+	}
+
+	return (1);
+}
+
+void
+rmaliases(void)
+{
+	struct alias *ap, **app;
+	int i;
+
+	INTOFF;
+	for (i = 0; i < ATABSIZE; i++) {
+		app = &atab[i];
+		for (ap = *app; ap; ap = *app) {
+			*app = freealias(*app);
+			if (ap == *app) {
+				app = &ap->next;
+			}
+		}
+	}
+	INTON;
+}
+
+struct alias *
+lookupalias(const char *name, int check)
+{
+	struct alias *ap = *__lookupalias(name);
+
+	if (check && ap && (ap->flag & ALIASINUSE))
+		return (NULL);
+	return (ap);
+}
+
+/*
+ * TODO - sort output
+ */
+int
+aliascmd(int argc, char **argv)
+{
+	char *n, *v;
+	int ret = 0;
+	struct alias *ap;
+
+	if (argc == 1) {
+		int i;
+
+		for (i = 0; i < ATABSIZE; i++)
+			for (ap = atab[i]; ap; ap = ap->next) {
+				printalias(ap);
+			}
+		return (0);
+	}
+	while ((n = *++argv) != NULL) {
+		if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
+			if ((ap = *__lookupalias(n)) == NULL) {
+				outfmt(out2, "%s: %s not found\n", "alias", n);
+				ret = 1;
+			} else
+				printalias(ap);
+		} else {
+			*v++ = '\0';
+			setalias(n, v);
+		}
+	}
+
+	return (ret);
+}
+
+int
+unaliascmd(int argc, char **argv)
+{
+	int i;
+
+	while ((i = nextopt("a")) != '\0') {
+		if (i == 'a') {
+			rmaliases();
+			return (0);
+		}
+	}
+	for (i = 0; *argptr; argptr++) {
+		if (unalias(*argptr)) {
+			outfmt(out2, "%s: %s not found\n", "unalias", *argptr);
+			i = 1;
+		}
+	}
+
+	return (i);
+}
+
+STATIC struct alias *
+freealias(struct alias *ap) {
+	struct alias *next;
+
+	if (ap->flag & ALIASINUSE) {
+		ap->flag |= ALIASDEAD;
+		return ap;
+	}
+
+	next = ap->next;
+	ckfree(ap->name);
+	ckfree(ap->val);
+	ckfree(ap);
+	return next;
+}
+
+void
+printalias(const struct alias *ap) {
+	out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
+}
+
+STATIC struct alias **
+__lookupalias(const char *name) {
+	unsigned int hashval;
+	struct alias **app;
+	const char *p;
+	unsigned int ch;
+
+	p = name;
+
+	ch = (unsigned char)*p;
+	hashval = ch << 4;
+	while (ch) {
+		hashval += ch;
+		ch = (unsigned char)*++p;
+	}
+	app = &atab[hashval % ATABSIZE];
+
+	for (; *app; app = &(*app)->next) {
+		if (equal(name, (*app)->name)) {
+			break;
+		}
+	}
+
+	return app;
+}
diff --git a/bin/dash/src/alias.h b/bin/dash/src/alias.h
new file mode 100644
index 00000000..fb841d64
--- /dev/null
+++ b/bin/dash/src/alias.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)alias.h	8.2 (Berkeley) 5/4/95
+ */
+
+#define ALIASINUSE	1
+#define ALIASDEAD	2
+
+struct alias {
+	struct alias *next;
+	char *name;
+	char *val;
+	int flag;
+};
+
+struct alias *lookupalias(const char *, int);
+int aliascmd(int, char **);
+int unaliascmd(int, char **);
+void rmaliases(void);
+int unalias(const char *);
+void printalias(const struct alias *);
diff --git a/bin/dash/src/arith_yacc.c b/bin/dash/src/arith_yacc.c
new file mode 100644
index 00000000..1a087c32
--- /dev/null
+++ b/bin/dash/src/arith_yacc.c
@@ -0,0 +1,304 @@
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2007
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include "arith_yacc.h"
+#include "expand.h"
+#include "shell.h"
+#include "error.h"
+#include "output.h"
+#include "var.h"
+
+#if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
+#error Arithmetic tokens are out of order.
+#endif
+
+static const char *arith_startbuf;
+
+const char *arith_buf;
+union yystype yylval;
+
+static int last_token;
+
+#define ARITH_PRECEDENCE(op, prec) [op - ARITH_BINOP_MIN] = prec
+
+static const char prec[ARITH_BINOP_MAX - ARITH_BINOP_MIN] = {
+	ARITH_PRECEDENCE(ARITH_MUL, 0),
+	ARITH_PRECEDENCE(ARITH_DIV, 0),
+	ARITH_PRECEDENCE(ARITH_REM, 0),
+	ARITH_PRECEDENCE(ARITH_ADD, 1),
+	ARITH_PRECEDENCE(ARITH_SUB, 1),
+	ARITH_PRECEDENCE(ARITH_LSHIFT, 2),
+	ARITH_PRECEDENCE(ARITH_RSHIFT, 2),
+	ARITH_PRECEDENCE(ARITH_LT, 3),
+	ARITH_PRECEDENCE(ARITH_LE, 3),
+	ARITH_PRECEDENCE(ARITH_GT, 3),
+	ARITH_PRECEDENCE(ARITH_GE, 3),
+	ARITH_PRECEDENCE(ARITH_EQ, 4),
+	ARITH_PRECEDENCE(ARITH_NE, 4),
+	ARITH_PRECEDENCE(ARITH_BAND, 5),
+	ARITH_PRECEDENCE(ARITH_BXOR, 6),
+	ARITH_PRECEDENCE(ARITH_BOR, 7),
+};
+
+#define ARITH_MAX_PREC 8
+
+static void yyerror(const char *s) __attribute__ ((noreturn));
+static void yyerror(const char *s)
+{
+	sh_error("arithmetic expression: %s: \"%s\"", s, arith_startbuf);
+	/* NOTREACHED */
+}
+
+static inline int arith_prec(int op)
+{
+	return prec[op - ARITH_BINOP_MIN];
+}
+
+static inline int higher_prec(int op1, int op2)
+{
+	return arith_prec(op1) < arith_prec(op2);
+}
+
+static intmax_t do_binop(int op, intmax_t a, intmax_t b)
+{
+	switch (op) {
+	default:
+	case ARITH_REM:
+	case ARITH_DIV:
+		if (!b)
+			yyerror("division by zero");
+		return op == ARITH_REM ? a % b : a / b;
+	case ARITH_MUL:
+		return a * b;
+	case ARITH_ADD:
+		return a + b;
+	case ARITH_SUB:
+		return a - b;
+	case ARITH_LSHIFT:
+		return a << b;
+	case ARITH_RSHIFT:
+		return a >> b;
+	case ARITH_LT:
+		return a < b;
+	case ARITH_LE:
+		return a <= b;
+	case ARITH_GT:
+		return a > b;
+	case ARITH_GE:
+		return a >= b;
+	case ARITH_EQ:
+		return a == b;
+	case ARITH_NE:
+		return a != b;
+	case ARITH_BAND:
+		return a & b;
+	case ARITH_BXOR:
+		return a ^ b;
+	case ARITH_BOR:
+		return a | b;
+	}
+}
+
+static intmax_t assignment(int var, int noeval);
+
+static intmax_t primary(int token, union yystype *val, int op, int noeval)
+{
+	intmax_t result;
+
+again:
+	switch (token) {
+	case ARITH_LPAREN:
+		result = assignment(op, noeval);
+		if (last_token != ARITH_RPAREN)
+			yyerror("expecting ')'");
+		last_token = yylex();
+		return result;
+	case ARITH_NUM:
+		last_token = op;
+		return val->val;
+	case ARITH_VAR:
+		last_token = op;
+		return noeval ? val->val : lookupvarint(val->name);
+	case ARITH_ADD:
+		token = op;
+		*val = yylval;
+		op = yylex();
+		goto again;
+	case ARITH_SUB:
+		*val = yylval;
+		return -primary(op, val, yylex(), noeval);
+	case ARITH_NOT:
+		*val = yylval;
+		return !primary(op, val, yylex(), noeval);
+	case ARITH_BNOT:
+		*val = yylval;
+		return ~primary(op, val, yylex(), noeval);
+	default:
+		yyerror("expecting primary");
+	}
+}
+
+static intmax_t binop2(intmax_t a, int op, int prec, int noeval)
+{
+	for (;;) {
+		union yystype val;
+		intmax_t b;
+		int op2;
+		int token;
+
+		token = yylex();
+		val = yylval;
+
+		b = primary(token, &val, yylex(), noeval);
+
+		op2 = last_token;
+		if (op2 >= ARITH_BINOP_MIN && op2 < ARITH_BINOP_MAX &&
+		    higher_prec(op2, op)) {
+			b = binop2(b, op2, arith_prec(op), noeval);
+			op2 = last_token;
+		}
+
+		a = noeval ? b : do_binop(op, a, b);
+
+		if (op2 < ARITH_BINOP_MIN || op2 >= ARITH_BINOP_MAX ||
+		    arith_prec(op2) >= prec)
+			return a;
+
+		op = op2;
+	}
+}
+
+static intmax_t binop(int token, union yystype *val, int op, int noeval)
+{
+	intmax_t a = primary(token, val, op, noeval);
+
+	op = last_token;
+	if (op < ARITH_BINOP_MIN || op >= ARITH_BINOP_MAX)
+		return a;
+
+	return binop2(a, op, ARITH_MAX_PREC, noeval);
+}
+
+static intmax_t and(int token, union yystype *val, int op, int noeval)
+{
+	intmax_t a = binop(token, val, op, noeval);
+	intmax_t b;
+
+	op = last_token;
+	if (op != ARITH_AND)
+		return a;
+
+	token = yylex();
+	*val = yylval;
+
+	b = and(token, val, yylex(), noeval | !a);
+
+	return a && b;
+}
+
+static intmax_t or(int token, union yystype *val, int op, int noeval)
+{
+	intmax_t a = and(token, val, op, noeval);
+	intmax_t b;
+
+	op = last_token;
+	if (op != ARITH_OR)
+		return a;
+
+	token = yylex();
+	*val = yylval;
+
+	b = or(token, val, yylex(), noeval | !!a);
+
+	return a || b;
+}
+
+static intmax_t cond(int token, union yystype *val, int op, int noeval)
+{
+	intmax_t a = or(token, val, op, noeval);
+	intmax_t b;
+	intmax_t c;
+
+	if (last_token != ARITH_QMARK)
+		return a;
+
+	b = assignment(yylex(), noeval | !a);
+
+	if (last_token != ARITH_COLON)
+		yyerror("expecting ':'");
+
+	token = yylex();
+	*val = yylval;
+
+	c = cond(token, val, yylex(), noeval | !!a);
+
+	return a ? b : c;
+}
+
+static intmax_t assignment(int var, int noeval)
+{
+	union yystype val = yylval;
+	int op = yylex();
+	intmax_t result;
+
+	if (var != ARITH_VAR)
+		return cond(var, &val, op, noeval);
+
+	if (op != ARITH_ASS && (op < ARITH_ASS_MIN || op >= ARITH_ASS_MAX))
+		return cond(var, &val, op, noeval);
+
+	result = assignment(yylex(), noeval);
+	if (noeval)
+		return result;
+
+	return setvarint(val.name,
+			 op == ARITH_ASS ? result :
+			 do_binop(op - 11, lookupvarint(val.name), result), 0);
+}
+
+intmax_t arith(const char *s)
+{
+	intmax_t result;
+
+	arith_buf = arith_startbuf = s;
+
+	result = assignment(yylex(), 0);
+
+	if (last_token)
+		yyerror("expecting EOF");
+
+	return result;
+}
diff --git a/bin/dash/src/arith_yacc.h b/bin/dash/src/arith_yacc.h
new file mode 100644
index 00000000..ff34d524
--- /dev/null
+++ b/bin/dash/src/arith_yacc.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2007
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#define ARITH_ASS 1
+
+#define ARITH_OR 2
+#define ARITH_AND 3
+#define ARITH_BAD 4
+#define ARITH_NUM 5
+#define ARITH_VAR 6
+#define ARITH_NOT 7
+
+#define ARITH_BINOP_MIN 8
+#define ARITH_LE 8
+#define ARITH_GE 9
+#define ARITH_LT 10
+#define ARITH_GT 11
+#define ARITH_EQ 12
+#define ARITH_REM 13
+#define ARITH_BAND 14
+#define ARITH_LSHIFT 15
+#define ARITH_RSHIFT 16
+#define ARITH_MUL 17
+#define ARITH_ADD 18
+#define ARITH_BOR 19
+#define ARITH_SUB 20
+#define ARITH_BXOR 21
+#define ARITH_DIV 22
+#define ARITH_NE 23
+#define ARITH_BINOP_MAX 24
+
+#define ARITH_ASS_MIN 24
+#define ARITH_REMASS 24
+#define ARITH_BANDASS 25
+#define ARITH_LSHIFTASS 26
+#define ARITH_RSHIFTASS 27
+#define ARITH_MULASS 28
+#define ARITH_ADDASS 29
+#define ARITH_BORASS 30
+#define ARITH_SUBASS 31
+#define ARITH_BXORASS 32
+#define ARITH_DIVASS 33
+#define ARITH_ASS_MAX 34
+
+#define ARITH_LPAREN 34
+#define ARITH_RPAREN 35
+#define ARITH_BNOT 36
+#define ARITH_QMARK 37
+#define ARITH_COLON 38
+
+union yystype {
+	intmax_t val;
+	char *name;
+};
+
+extern union yystype yylval;
+
+int yylex(void);
diff --git a/bin/dash/src/arith_yylex.c b/bin/dash/src/arith_yylex.c
new file mode 100644
index 00000000..ec5b5b25
--- /dev/null
+++ b/bin/dash/src/arith_yylex.c
@@ -0,0 +1,240 @@
+/*-
+ * Copyright (c) 2002
+ *	Herbert Xu.
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include "arith_yacc.h"
+#include "expand.h"
+#include "error.h"
+#include "shell.h"
+#include "memalloc.h"
+#include "syntax.h"
+#include "system.h"
+
+#if ARITH_BOR + 11 != ARITH_BORASS || ARITH_ASS + 11 != ARITH_EQ
+#error Arithmetic tokens are out of order.
+#endif
+
+extern const char *arith_buf;
+
+int
+yylex()
+{
+	int value;
+	const char *buf = arith_buf;
+	const char *p;
+
+	for (;;) {
+		value = *buf;
+		switch (value) {
+		case ' ':
+		case '\t':
+		case '\n':
+			buf++;
+			continue;
+		default:
+			return ARITH_BAD;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			yylval.val = strtoimax(buf, (char **)&arith_buf, 0);
+			return ARITH_NUM;
+		case 'A':
+		case 'B':
+		case 'C':
+		case 'D':
+		case 'E':
+		case 'F':
+		case 'G':
+		case 'H':
+		case 'I':
+		case 'J':
+		case 'K':
+		case 'L':
+		case 'M':
+		case 'N':
+		case 'O':
+		case 'P':
+		case 'Q':
+		case 'R':
+		case 'S':
+		case 'T':
+		case 'U':
+		case 'V':
+		case 'W':
+		case 'X':
+		case 'Y':
+		case 'Z':
+		case '_':
+		case 'a':
+		case 'b':
+		case 'c':
+		case 'd':
+		case 'e':
+		case 'f':
+		case 'g':
+		case 'h':
+		case 'i':
+		case 'j':
+		case 'k':
+		case 'l':
+		case 'm':
+		case 'n':
+		case 'o':
+		case 'p':
+		case 'q':
+		case 'r':
+		case 's':
+		case 't':
+		case 'u':
+		case 'v':
+		case 'w':
+		case 'x':
+		case 'y':
+		case 'z':
+			p = buf;
+			while (buf++, is_in_name(*buf))
+				;
+			yylval.name = stalloc(buf - p + 1);
+			*(char *)mempcpy(yylval.name, p, buf - p) = 0;
+			value = ARITH_VAR;
+			goto out;
+		case '=':
+			value += ARITH_ASS - '=';
+checkeq:
+			buf++;
+checkeqcur:
+			if (*buf != '=')
+				goto out;
+			value += 11;
+			break;
+		case '>':
+			switch (*++buf) {
+			case '=':
+				value += ARITH_GE - '>';
+				break;
+			case '>':
+				value += ARITH_RSHIFT - '>';
+				goto checkeq;
+			default:
+				value += ARITH_GT - '>';
+				goto out;
+			}
+			break;
+		case '<':
+			switch (*++buf) {
+			case '=':
+				value += ARITH_LE - '<';
+				break;
+			case '<':
+				value += ARITH_LSHIFT - '<';
+				goto checkeq;
+			default:
+				value += ARITH_LT - '<';
+				goto out;
+			}
+			break;
+		case '|':
+			if (*++buf != '|') {
+				value += ARITH_BOR - '|';
+				goto checkeqcur;
+			}
+			value += ARITH_OR - '|';
+			break;
+		case '&':
+			if (*++buf != '&') {
+				value += ARITH_BAND - '&';
+				goto checkeqcur;
+			}
+			value += ARITH_AND - '&';
+			break;
+		case '!':
+			if (*++buf != '=') {
+				value += ARITH_NOT - '!';
+				goto out;
+			}
+			value += ARITH_NE - '!';
+			break;
+		case 0:
+			goto out;
+		case '(':
+			value += ARITH_LPAREN - '(';
+			break;
+		case ')':
+			value += ARITH_RPAREN - ')';
+			break;
+		case '*':
+			value += ARITH_MUL - '*';
+			goto checkeq;
+		case '/':
+			value += ARITH_DIV - '/';
+			goto checkeq;
+		case '%':
+			value += ARITH_REM - '%';
+			goto checkeq;
+		case '+':
+			value += ARITH_ADD - '+';
+			goto checkeq;
+		case '-':
+			value += ARITH_SUB - '-';
+			goto checkeq;
+		case '~':
+			value += ARITH_BNOT - '~';
+			break;
+		case '^':
+			value += ARITH_BXOR - '^';
+			goto checkeq;
+		case '?':
+			value += ARITH_QMARK - '?';
+			break;
+		case ':':
+			value += ARITH_COLON - ':';
+			break;
+		}
+		break;
+	}
+
+	buf++;
+out:
+	arith_buf = buf;
+	return value;
+}
diff --git a/bin/dash/src/bltin/bltin.h b/bin/dash/src/bltin/bltin.h
new file mode 100644
index 00000000..f5ac06f2
--- /dev/null
+++ b/bin/dash/src/bltin/bltin.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)bltin.h	8.1 (Berkeley) 5/31/93
+ */
+
+/*
+ * This file is included by programs which are optionally built into the
+ * shell.  If SHELL is defined, we try to map the standard UNIX library
+ * routines to ash routines using defines.
+ */
+
+#include "../shell.h"
+#include "../mystring.h"
+#include "../options.h"
+#ifdef SHELL
+#include "../memalloc.h"
+#include "../output.h"
+#include "../error.h"
+#ifndef USE_GLIBC_STDIO
+#undef stdout
+#undef stderr
+#undef putc
+#undef putchar
+#undef fileno
+#define stdout out1
+#define stderr out2
+#define printf out1fmt
+#define putc(c, file)	outc(c, file)
+#define putchar(c)	out1c(c)
+#define FILE struct output
+#define fprintf outfmt
+#define fputs outstr
+#define fflush flushout
+#define fileno(f) ((f)->fd)
+#define ferror outerr
+#endif
+#define INITARGS(argv)
+#define	error sh_error
+#define	warn sh_warn
+#define	warnx sh_warnx
+#define exit sh_exit
+#define setprogname(s)
+#define getprogname() commandname
+#define setlocate(l,s) 0
+
+#define getenv(p) bltinlookup((p),0)
+
+#else
+#undef NULL
+#include <stdio.h>
+#undef main
+#define INITARGS(argv)	if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
+#endif
+
+int echocmd(int, char **);
+
+
+extern const char *commandname;
diff --git a/bin/dash/src/bltin/echo.1 b/bin/dash/src/bltin/echo.1
new file mode 100644
index 00000000..fbc7fb43
--- /dev/null
+++ b/bin/dash/src/bltin/echo.1
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1997-2005
+.\"	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Kenneth Almquist.
+.\" Copyright 1989 by Kenneth Almquist
+.\"
+.\" 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.
+.\" 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"	@(#)echo.1	8.1 (Berkeley) 5/31/93
+.\"
+.Dd May 31, 1993
+.Dt ECHO 1
+.Os
+.Sh NAME
+.Nm echo
+.Nd produce message in a shell script
+.Sh SYNOPSIS
+.Nm
+.Op Fl n | Fl e
+.Ar args ...
+.Sh DESCRIPTION
+.Nm
+prints its arguments on the standard output, separated by spaces.
+Unless the
+.Fl n
+option is present, a newline is output following the arguments.
+The
+.Fl e
+option causes
+.Nm
+to treat the escape sequences specially, as described in the following
+paragraph.
+The
+.Fl e
+option is the default, and is provided solely for compatibility with
+other systems.
+Only one of the options
+.Fl n
+and
+.Fl e
+may be given.
+.Pp
+If any of the following sequences of characters is encountered during
+output, the sequence is not output.  Instead, the specified action is
+performed:
+.Bl -tag -width indent
+.It Li \eb
+A backspace character is output.
+.It Li \ec
+Subsequent output is suppressed.  This is normally used at the end of the
+last argument to suppress the trailing newline that
+.Nm
+would otherwise output.
+.It Li \ef
+Output a form feed.
+.It Li \en
+Output a newline character.
+.It Li \er
+Output a carriage return.
+.It Li \et
+Output a (horizontal) tab character.
+.It Li \ev
+Output a vertical tab.
+.It Li \e0 Ns Ar digits
+Output the character whose value is given by zero to three digits.
+If there are zero digits, a nul character is output.
+.It Li \e\e
+Output a backslash.
+.El
+.Sh HINTS
+Remember that backslash is special to the shell and needs to be escaped.
+To output a message to standard error, say
+.Pp
+.D1  echo message \*[Gt]\*[Am]2
+.Sh BUGS
+The octal character escape mechanism
+.Pq Li \e0 Ns Ar digits
+differs from the
+C language mechanism.
+.Pp
+There is no way to force
+.Nm
+to treat its arguments literally, rather than interpreting them as
+options and escape sequences.
diff --git a/bin/dash/src/bltin/printf.1 b/bin/dash/src/bltin/printf.1
new file mode 100644
index 00000000..38731732
--- /dev/null
+++ b/bin/dash/src/bltin/printf.1
@@ -0,0 +1,354 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1997-2005
+.\"	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" 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.
+.\" 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"	from: @(#)printf.1	8.1 (Berkeley) 6/6/93
+.\"
+.Dd November 5, 1993
+.Dt PRINTF 1
+.Os
+.Sh NAME
+.Nm printf
+.Nd formatted output
+.Sh SYNOPSIS
+.Nm
+.Ar format
+.Op Ar arguments  ...
+.Sh DESCRIPTION
+.Nm
+formats and prints its arguments, after the first, under control
+of the
+.Ar format  .
+The
+.Ar format
+is a character string which contains three types of objects: plain characters,
+which are simply copied to standard output, character escape sequences which
+are converted and copied to the standard output, and format specifications,
+each of which causes printing of the next successive
+.Ar argument  .
+.Pp
+The
+.Ar arguments
+after the first are treated as strings if the corresponding format is
+either
+.Cm b ,
+.Cm B ,
+.Cm c
+or
+.Cm s ;
+otherwise it is evaluated as a C constant, with the following extensions:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+A leading plus or minus sign is allowed.
+.It
+If the leading character is a single or double quote, the value is the
+.Tn ASCII
+code of the next character.
+.El
+.Pp
+The format string is reused as often as necessary to satisfy the
+.Ar arguments  .
+Any extra format specifications are evaluated with zero or the null
+string.
+.Pp
+Character escape sequences are in backslash notation as defined in
+.St -ansiC .
+The characters and their meanings are as follows:
+.Bl -tag -width Ds -offset indent
+.It Cm \ee
+Write an \*[Lt]escape\*[Gt] character.
+.It Cm \ea
+Write a \*[Lt]bell\*[Gt] character.
+.It Cm \eb
+Write a \*[Lt]backspace\*[Gt] character.
+.It Cm \ef
+Write a \*[Lt]form-feed\*[Gt] character.
+.It Cm \en
+Write a \*[Lt]new-line\*[Gt] character.
+.It Cm \er
+Write a \*[Lt]carriage return\*[Gt] character.
+.It Cm \et
+Write a \*[Lt]tab\*[Gt] character.
+.It Cm \ev
+Write a \*[Lt]vertical tab\*[Gt] character.
+.It Cm \e\'
+Write a \*[Lt]single quote\*[Gt] character.
+.It Cm \e"
+Write a \*[Lt]double quote\*[Gt] character.
+.It Cm \e\e
+Write a backslash character.
+.It Cm \e Ns Ar num
+Write an 8\-bit character whose
+.Tn ASCII
+value is the 1\-, 2\-, or 3\-digit octal number
+.Ar num .
+.It Cm \ex Ns Ar xx
+Write an 8\-bit character whose
+.Tn ASCII
+value is the 1\- or 2\-digit hexadecimal number
+.Ar xx .
+.El
+.Pp
+Each format specification is introduced by the percent character
+(``%'').
+The remainder of the format specification includes,
+in the following order:
+.Bl -tag -width Ds
+.It "Zero or more of the following flags:"
+.Bl -tag -width Ds
+.It Cm #
+A `#' character
+specifying that the value should be printed in an ``alternative form''.
+For
+.Cm b ,
+.Cm c ,
+.Cm d ,
+and
+.Cm s
+formats, this option has no effect.
+For the
+.Cm o
+format the precision of the number is increased to force the first
+character of the output string to a zero.
+For the
+.Cm x
+.Pq Cm X
+format, a non-zero result has the string
+.Li 0x
+.Pq Li 0X
+prepended to it.
+For
+.Cm e  ,
+.Cm E ,
+.Cm f  ,
+.Cm g ,
+and
+.Cm G
+formats, the result will always contain a decimal point, even if no
+digits follow the point (normally, a decimal point only appears in the
+results of those formats if a digit follows the decimal point).
+For
+.Cm g
+and
+.Cm G
+formats, trailing zeros are not removed from the result as they
+would otherwise be.
+.\" I turned this off - decided it isn't a valid use of '#'
+.\" For the
+.\" .Cm B
+.\" format, backslash-escape sequences are expanded first;
+.It Cm \&\-
+A minus sign `\-' which specifies
+.Em left adjustment
+of the output in the indicated field;
+.It Cm \&+
+A `+' character specifying that there should always be
+a sign placed before the number when using signed formats.
+.It Sq \&\ \&
+A space specifying that a blank should be left before a positive number
+for a signed format.
+A `+' overrides a space if both are used;
+.It Cm \&0
+A zero `0' character indicating that zero-padding should be used
+rather than blank-padding.
+A `\-' overrides a `0' if both are used;
+.El
+.It "Field Width:"
+An optional digit string specifying a
+.Em field width ;
+if the output string has fewer characters than the field width it will
+be blank-padded on the left (or right, if the left-adjustment indicator
+has been given) to make up the field width (note that a leading zero
+is a flag, but an embedded zero is part of a field width);
+.It Precision :
+An optional period,
+.Sq Cm \&.\& ,
+followed by an optional digit string giving a
+.Em precision
+which specifies the number of digits to appear after the decimal point,
+for
+.Cm e
+and
+.Cm f
+formats, or the maximum number of characters to be printed
+from a string
+.Sm off
+.Pf ( Cm b No ,
+.Sm on
+.Cm B
+and
+.Cm s
+formats); if the digit string is missing, the precision is treated
+as zero;
+.It Format :
+A character which indicates the type of format to use (one of
+.Cm diouxXfwEgGbBcs ) .
+.El
+.Pp
+A field width or precision may be
+.Sq Cm \&*
+instead of a digit string.
+In this case an
+.Ar argument
+supplies the field width or precision.
+.Pp
+The format characters and their meanings are:
+.Bl -tag -width Fl
+.It Cm diouXx
+The
+.Ar argument
+is printed as a signed decimal (d or i), unsigned octal, unsigned decimal,
+or unsigned hexadecimal (X or x), respectively.
+.It Cm f
+The
+.Ar argument
+is printed in the style
+.Sm off
+.Pf [\-]ddd Cm \&. No ddd
+.Sm on
+where the number of d's
+after the decimal point is equal to the precision specification for
+the argument.
+If the precision is missing, 6 digits are given; if the precision
+is explicitly 0, no digits and no decimal point are printed.
+.It Cm eE
+The
+.Ar argument
+is printed in the style
+.Sm off
+.Pf [\-]d Cm \&. No ddd Cm e No \\*(Pmdd
+.Sm on
+where there
+is one digit before the decimal point and the number after is equal to
+the precision specification for the argument; when the precision is
+missing, 6 digits are produced.
+An upper-case E is used for an `E' format.
+.It Cm gG
+The
+.Ar argument
+is printed in style
+.Cm f
+or in style
+.Cm e
+.Pq Cm E
+whichever gives full precision in minimum space.
+.It Cm b
+Characters from the string
+.Ar argument
+are printed with backslash-escape sequences expanded.
+.br
+The following additional backslash-escape sequences are supported:
+.Bl -tag -width Ds
+.It Cm \ec
+Causes
+.Nm
+to ignore any remaining characters in the string operand containing it,
+any remaining string operands, and any additional characters in
+the format operand.
+.It Cm \e0 Ns Ar num
+Write an 8\-bit character whose
+.Tn ASCII
+value is the 1\-, 2\-, or 3\-digit
+octal number
+.Ar num .
+.It Cm \e^ Ns Ar c
+Write the control character 
+.Ar c .
+Generates characters `\e000' through `\e037`, and `\e177' (from `\e^?').
+.It Cm \eM\- Ns Ar c
+Write the character 
+.Ar c
+with the 8th bit set.
+Generates characters `\e241' through `\e376`.
+.It Cm \eM^ Ns Ar c
+Write the control character 
+.Ar c
+with the 8th bit set.
+Generates characters `\e000' through `\e037`, and `\e177' (from `\eM^?').
+.El
+.It Cm B
+Characters from the string
+.Ar argument
+are printed with unprintable characters backslash-escaped using the
+.Sm off
+.Pf ` Cm \e Ar c No ',
+.Pf ` Cm \e^ Ar c No ',
+.Pf ` Cm \eM\- Ar c No '
+or
+.Pf ` Cm \eM^ Ar c No ',
+.Sm on
+formats described above.
+.It Cm c
+The first character of
+.Ar argument
+is printed.
+.It Cm s
+Characters from the string
+.Ar argument
+are printed until the end is reached or until the number of characters
+indicated by the precision specification is reached; if the
+precision is omitted, all characters in the string are printed.
+.It Cm \&%
+Print a `%'; no argument is used.
+.El
+.Pp
+In no case does a non-existent or small field width cause truncation of
+a field; padding takes place only if the specified field width exceeds
+the actual width.
+.Sh EXIT STATUS
+.Nm
+exits 0 on success, 1 on failure.
+.Sh SEE ALSO
+.Xr echo 1 ,
+.Xr printf 3 ,
+.Xr printf 9
+.Xr vis 3
+.Sh STANDARDS
+The
+.Nm
+utility conforms to
+.St -p1003.1-2001 .
+.Pp
+Support for the floating point formats and `*' as a field width and precision
+are optional in POSIX.
+.Pp
+The behaviour of the %B format and the \e', \e", \exxx, \ee and
+\e[M][\-|^]c escape sequences are undefined in POSIX.
+.Sh BUGS
+Since the floating point numbers are translated from
+.Tn ASCII
+to floating-point and
+then back again, floating-point precision may be lost.
+.Pp
+Hexadecimal character constants are restricted to, and should be specified
+as, two character constants.  This is contrary to the ISO C standard but
+does guarantee detection of the end of the constant.
diff --git a/bin/dash/src/bltin/printf.c b/bin/dash/src/bltin/printf.c
new file mode 100644
index 00000000..7785735b
--- /dev/null
+++ b/bin/dash/src/bltin/printf.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int	 conv_escape_str(char *, char **);
+static char	*conv_escape(char *, int *);
+static int	 getchr(void);
+static double	 getdouble(void);
+static uintmax_t getuintmax(int);
+static char	*getstr(void);
+static char	*mklong(const char *, const char *);
+static void      check_conversion(const char *, const char *);
+
+static int	rval;
+static char  **gargv;
+
+#define isodigit(c)	((c) >= '0' && (c) <= '7')
+#define octtobin(c)	((c) - '0')
+
+#include "bltin.h"
+#include "system.h"
+
+#define PF(f, func) { \
+	switch ((char *)param - (char *)array) { \
+	default: \
+		(void)printf(f, array[0], array[1], func); \
+		break; \
+	case sizeof(*param): \
+		(void)printf(f, array[0], func); \
+		break; \
+	case 0: \
+		(void)printf(f, func); \
+		break; \
+	} \
+}
+
+#define ASPF(sp, f, func) ({ \
+	int ret; \
+	switch ((char *)param - (char *)array) { \
+	default: \
+		ret = xasprintf(sp, f, array[0], array[1], func); \
+		break; \
+	case sizeof(*param): \
+		ret = xasprintf(sp, f, array[0], func); \
+		break; \
+	case 0: \
+		ret = xasprintf(sp, f, func); \
+		break; \
+	} \
+	ret; \
+})
+
+
+static int print_escape_str(const char *f, int *param, int *array, char *s)
+{
+	struct stackmark smark;
+	char *p, *q;
+	int done;
+	int len;
+	int total;
+
+	setstackmark(&smark);
+	done = conv_escape_str(s, &q);
+	p = stackblock();
+	len = q - p;
+	total = len - 1;
+
+	q[-1] = (!!((f[1] - 's') | done) - 1) & f[2];
+	total += !!q[-1];
+	if (f[1] == 's')
+		goto easy;
+
+	p = makestrspace(len, q);
+	memset(p, 'X', total);
+	p[total] = 0;
+
+	q = stackblock();
+	total = ASPF(&p, f, p);
+
+	len = strchrnul(p, 'X') - p;
+	memcpy(p + len, q, strspn(p + len, "X"));
+
+easy:
+	out1mem(p, total);
+
+	popstackmark(&smark);
+	return done;
+}
+
+
+int printfcmd(int argc, char *argv[])
+{
+	char *fmt;
+	char *format;
+	int ch;
+
+	rval = 0;
+
+	nextopt(nullstr);
+
+	argv = argptr;
+	format = *argv;
+
+	if (!format)
+		error("usage: printf format [arg ...]");
+
+	gargv = ++argv;
+
+#define SKIP1	"#-+ 0"
+#define SKIP2	"*0123456789"
+	do {
+		/*
+		 * Basic algorithm is to scan the format string for conversion
+		 * specifications -- once one is found, find out if the field
+		 * width or precision is a '*'; if it is, gather up value. 
+		 * Note, format strings are reused as necessary to use up the
+		 * provided arguments, arguments of zero/null string are 
+		 * provided to use up the format string.
+		 */
+
+		/* find next format specification */
+		for (fmt = format; (ch = *fmt++) ;) {
+			char *start;
+			char nextch;
+			int array[2];
+			int *param;
+
+			if (ch == '\\') {
+				int c_ch;
+				fmt = conv_escape(fmt, &c_ch);
+				ch = c_ch;
+				goto pc;
+			}
+			if (ch != '%' || (*fmt == '%' && (++fmt || 1))) {
+pc:
+				putchar(ch);
+				continue;
+			}
+
+			/* Ok - we've found a format specification,
+			   Save its address for a later printf(). */
+			start = fmt - 1;
+			param = array;
+
+			/* skip to field width */
+			fmt += strspn(fmt, SKIP1);
+			if (*fmt == '*') {
+				++fmt;
+				*param++ = getuintmax(1);
+			} else {
+				/* skip to possible '.',
+				 * get following precision
+				 */
+				fmt += strspn(fmt, SKIP2);
+			}
+
+			if (*fmt == '.') {
+				++fmt;
+				if (*fmt == '*') {
+					++fmt;
+					*param++ = getuintmax(1);
+				} else
+					fmt += strspn(fmt, SKIP2);
+			}
+
+			ch = *fmt;
+			if (!ch)
+				error("missing format character");
+			/* null terminate format string to we can use it
+			   as an argument to printf. */
+			nextch = fmt[1];
+			fmt[1] = 0;
+			switch (ch) {
+
+			case 'b':
+				*fmt = 's';
+				/* escape if a \c was encountered */
+				if (print_escape_str(start, param, array,
+						     getstr()))
+					goto out;
+				*fmt = 'b';
+				break;
+			case 'c': {
+				int p = getchr();
+				PF(start, p);
+				break;
+			}
+			case 's': {
+				char *p = getstr();
+				PF(start, p);
+				break;
+			}
+			case 'd':
+			case 'i': {
+				uintmax_t p = getuintmax(1);
+				start = mklong(start, fmt);
+				PF(start, p);
+				break;
+			}
+			case 'o':
+			case 'u':
+			case 'x':
+			case 'X': {
+				uintmax_t p = getuintmax(0);
+				start = mklong(start, fmt);
+				PF(start, p);
+				break;
+			}
+			case 'a':
+			case 'A':
+			case 'e':
+			case 'E':
+			case 'f':
+			case 'F':
+			case 'g':
+			case 'G': {
+				double p = getdouble();
+				PF(start, p);
+				break;
+			}
+			default:
+				error("%s: invalid directive", start);
+			}
+			*++fmt = nextch;
+		}
+	} while (gargv != argv && *gargv);
+
+out:
+	return rval;
+}
+
+
+/*
+ * Print SysV echo(1) style escape string 
+ *	Halts processing string if a \c escape is encountered.
+ */
+static int
+conv_escape_str(char *str, char **sp)
+{
+	int c;
+	int ch;
+	char *cp;
+
+	/* convert string into a temporary buffer... */
+	STARTSTACKSTR(cp);
+
+	do {
+		c = ch = *str++;
+		if (ch != '\\')
+			continue;
+
+		c = *str++;
+		if (c == 'c') {
+			/* \c as in SYSV echo - abort all processing.... */
+			c = ch = 0x100;
+			continue;
+		}
+
+		/* 
+		 * %b string octal constants are not like those in C.
+		 * They start with a \0, and are followed by 0, 1, 2, 
+		 * or 3 octal digits. 
+		 */
+		if (c == '0' && isodigit(*str))
+			str++;
+
+		/* Finally test for sequences valid in the format string */
+		str = conv_escape(str - 1, &c);
+	} while (STPUTC(c, cp), (char)ch);
+
+	*sp = cp;
+
+	return ch;
+}
+
+/*
+ * Print "standard" escape characters 
+ */
+static char *
+conv_escape(char *str, int *conv_ch)
+{
+	int value;
+	int ch;
+
+	ch = *str;
+
+	switch (ch) {
+	default:
+		if (!isodigit(*str)) {
+			value = '\\';
+			goto out;
+		}
+
+		ch = 3;
+		value = 0;
+		do {
+			value <<= 3;
+			value += octtobin(*str++);
+		} while (isodigit(*str) && --ch);
+		goto out;
+
+	case '\\':	value = '\\';	break;	/* backslash */
+	case 'a':	value = '\a';	break;	/* alert */
+	case 'b':	value = '\b';	break;	/* backspace */
+	case 'f':	value = '\f';	break;	/* form-feed */
+	case 'n':	value = '\n';	break;	/* newline */
+	case 'r':	value = '\r';	break;	/* carriage-return */
+	case 't':	value = '\t';	break;	/* tab */
+	case 'v':	value = '\v';	break;	/* vertical-tab */
+	}
+
+	str++;
+out:
+	*conv_ch = value;
+	return str;
+}
+
+static char *
+mklong(const char *str, const char *ch)
+{
+	/*
+	 * Replace a string like "%92.3u" with "%92.3"PRIuMAX.
+	 *
+	 * Although C99 does not guarantee it, we assume PRIiMAX,
+	 * PRIoMAX, PRIuMAX, PRIxMAX, and PRIXMAX are all the same
+	 * as PRIdMAX with the final 'd' replaced by the corresponding
+	 * character.
+	 */
+
+	char *copy;
+	size_t len;	
+
+	len = ch - str + sizeof(PRIdMAX);
+	STARTSTACKSTR(copy);
+	copy = makestrspace(len, copy);
+	memcpy(copy, str, len - sizeof(PRIdMAX));
+	memcpy(copy + len - sizeof(PRIdMAX), PRIdMAX, sizeof(PRIdMAX));
+	copy[len - 2] = *ch;
+	return (copy);	
+}
+
+static int
+getchr(void)
+{
+	int val = 0;
+
+	if (*gargv)
+		val = **gargv++;
+	return val;
+}
+
+static char *
+getstr(void)
+{
+	char *val = nullstr;
+
+	if (*gargv)
+		val = *gargv++;
+	return val;
+}
+
+static uintmax_t
+getuintmax(int sign)
+{
+	uintmax_t val = 0;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		goto out;
+	gargv++;
+
+	val = (unsigned char) cp[1];
+	if (*cp == '\"' || *cp == '\'')
+		goto out;
+
+	errno = 0;
+	val = sign ? strtoimax(cp, &ep, 0) : strtoumax(cp, &ep, 0);
+	check_conversion(cp, ep);
+out:
+	return val;
+}
+
+static double
+getdouble(void)
+{
+	double val;
+	char *cp, *ep;
+
+	cp = *gargv;
+	if (cp == NULL)
+		return 0;
+	gargv++;
+
+	if (*cp == '\"' || *cp == '\'')
+		return (unsigned char) cp[1];
+
+	errno = 0;
+	val = strtod(cp, &ep);
+	check_conversion(cp, ep);
+	return val;
+}
+
+static void
+check_conversion(const char *s, const char *ep)
+{
+	if (*ep) {
+		if (ep == s)
+			warnx("%s: expected numeric value", s);
+		else
+			warnx("%s: not completely converted", s);
+		rval = 1;
+	} else if (errno == ERANGE) {
+		warnx("%s: %s", s, strerror(ERANGE));
+		rval = 1;
+	}
+}
+
+int
+echocmd(int argc, char **argv)
+{
+	const char *lastfmt = snlfmt;
+	int nonl;
+
+	if (*++argv && equal(*argv, "-n")) {
+		argv++;
+		lastfmt = "%s";
+	}
+
+	do {
+		const char *fmt = "%s ";
+		char *s = *argv;
+
+		if (!s || !*++argv)
+			fmt = lastfmt;
+
+		nonl = print_escape_str(fmt, NULL, NULL, s ?: nullstr);
+	} while (!nonl && *argv);
+	return 0;
+}
diff --git a/bin/dash/src/bltin/test.1 b/bin/dash/src/bltin/test.1
new file mode 100644
index 00000000..42435fb3
--- /dev/null
+++ b/bin/dash/src/bltin/test.1
@@ -0,0 +1,309 @@
+.\" Copyright (c) 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1997-2005
+.\"	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Institute of Electrical and Electronics Engineers, Inc.
+.\"
+.\" 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.
+.\" 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"     @(#)test.1	8.1 (Berkeley) 5/31/93
+.\"
+.Dd May 31, 1993
+.Dt TEST 1
+.Os
+.Sh NAME
+.Nm test ,
+.Nm \&[
+.Nd condition evaluation utility
+.Sh SYNOPSIS
+.Nm test
+.Ar expression
+.Nm \&[
+.Ar expression Cm ]
+.Sh DESCRIPTION
+The
+.Nm test
+utility evaluates the expression and, if it evaluates
+to true, returns a zero (true) exit status; otherwise
+it returns 1 (false).
+If there is no expression, test also
+returns 1 (false).
+.Pp
+All operators and flags are separate arguments to the
+.Nm test
+utility.
+.Pp
+The following primaries are used to construct expression:
+.Bl -tag -width Ar
+.It Fl b Ar file
+True if
+.Ar file
+exists and is a block special
+file.
+.It Fl c Ar file
+True if
+.Ar file
+exists and is a character
+special file.
+.It Fl d Ar file
+True if
+.Ar file
+exists and is a directory.
+.It Fl e Ar file
+True if
+.Ar file
+exists (regardless of type).
+.It Fl f Ar file
+True if
+.Ar file
+exists and is a regular file.
+.It Fl g Ar file
+True if
+.Ar file
+exists and its set group ID flag
+is set.
+.It Fl h Ar file
+True if
+.Ar file
+exists and is a symbolic link.
+.It Fl k Ar file
+True if
+.Ar file
+exists and its sticky bit is set.
+.It Fl n Ar string
+True if the length of
+.Ar string
+is nonzero.
+.It Fl p Ar file
+True if
+.Ar file
+is a named pipe
+.Po Tn FIFO Pc .
+.It Fl r Ar file
+True if
+.Ar file
+exists and is readable.
+.It Fl s Ar file
+True if
+.Ar file
+exists and has a size greater
+than zero.
+.It Fl t Ar file_descriptor
+True if the file whose file descriptor number
+is
+.Ar file_descriptor
+is open and is associated with a terminal.
+.It Fl u Ar file
+True if
+.Ar file
+exists and its set user ID flag
+is set.
+.It Fl w Ar file
+True if
+.Ar file
+exists and is writable.
+True
+indicates only that the write flag is on.
+The file is not writable on a read-only file
+system even if this test indicates true.
+.It Fl x Ar file
+True if
+.Ar file
+exists and is executable.
+True
+indicates only that the execute flag is on.
+If
+.Ar file
+is a directory, true indicates that
+.Ar file
+can be searched.
+.It Fl z Ar string
+True if the length of
+.Ar string
+is zero.
+.It Fl L Ar file
+True if
+.Ar file
+exists and is a symbolic link.
+This operator is retained for compatibility with previous versions of
+this program.
+Do not rely on its existence; use
+.Fl h
+instead.
+.It Fl O Ar file
+True if
+.Ar file
+exists and its owner matches the effective user id of this process.
+.It Fl G Ar file
+True if
+.Ar file
+exists and its group matches the effective group id of this process.
+.It Fl S Ar file
+True if
+.Ar file
+exists and is a socket.
+.It Ar file1 Fl nt Ar file2
+True if
+.Ar file1
+exists and is newer than
+.Ar file2 .
+.It Ar file1 Fl ot Ar file2
+True if
+.Ar file1
+exists and is older than
+.Ar file2 .
+.It Ar file1 Fl ef Ar file2
+True if
+.Ar file1
+and
+.Ar file2
+exist and refer to the same file.
+.It Ar string
+True if
+.Ar string
+is not the null
+string.
+.It Ar \&s\&1 Cm \&= Ar \&s\&2
+True if the strings
+.Ar \&s\&1
+and
+.Ar \&s\&2
+are identical.
+.It Ar \&s\&1 Cm \&!= Ar \&s\&2
+True if the strings
+.Ar \&s\&1
+and
+.Ar \&s\&2
+are not identical.
+.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2
+True if string
+.Ar \&s\&1
+comes before
+.Ar \&s\&2
+based on the ASCII value of their characters.
+.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2
+True if string
+.Ar \&s\&1
+comes after
+.Ar \&s\&2
+based on the ASCII value of their characters.
+.It Ar \&n\&1 Fl \&eq Ar \&n\&2
+True if the integers
+.Ar \&n\&1
+and
+.Ar \&n\&2
+are algebraically
+equal.
+.It Ar \&n\&1 Fl \&ne Ar \&n\&2
+True if the integers
+.Ar \&n\&1
+and
+.Ar \&n\&2
+are not
+algebraically equal.
+.It Ar \&n\&1 Fl \&gt Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically
+greater than the integer
+.Ar \&n\&2 .
+.It Ar \&n\&1 Fl \&ge Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically
+greater than or equal to the integer
+.Ar \&n\&2 .
+.It Ar \&n\&1 Fl \&lt Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically less
+than the integer
+.Ar \&n\&2 .
+.It Ar \&n\&1 Fl \&le Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically less
+than or equal to the integer
+.Ar \&n\&2 .
+.El
+.Pp
+These primaries can be combined with the following operators:
+.Bl -tag -width Ar
+.It Cm \&! Ar expression
+True if
+.Ar expression
+is false.
+.It Ar expression1 Fl a Ar expression2
+True if both
+.Ar expression1
+and
+.Ar expression2
+are true.
+.It Ar expression1 Fl o Ar expression2
+True if either
+.Ar expression1
+or
+.Ar expression2
+are true.
+.It Cm \&( Ns Ar expression Ns Cm \&)
+True if expression is true.
+.El
+.Pp
+The
+.Fl a
+operator has higher precedence than the
+.Fl o
+operator.
+.Sh GRAMMAR AMBIGUITY
+The
+.Nm test
+grammar is inherently ambiguous.
+In order to assure a degree of consistency, the cases described in
+.St -p1003.2
+section 4.62.4,
+are evaluated consistently according to the rules specified in the
+standards document.
+All other cases are subject to the ambiguity in the command semantics.
+.Sh EXIT STATUS
+The
+.Nm test
+utility exits with one of the following values:
+.Bl -tag -width Ds
+.It 0
+expression evaluated to true.
+.It 1
+expression evaluated to false or expression was
+missing.
+.It \*[Gt]1
+An error occurred.
+.El
+.Sh STANDARDS
+The
+.Nm test
+utility implements a superset of the
+.St -p1003.2
+specification.
diff --git a/bin/dash/src/bltin/test.c b/bin/dash/src/bltin/test.c
new file mode 100644
index 00000000..c7fc479d
--- /dev/null
+++ b/bin/dash/src/bltin/test.c
@@ -0,0 +1,700 @@
+/*
+ * test(1); version 7-like  --  author Erik Baalbergen
+ * modified by Eric Gisin to be used as built-in.
+ * modified by Arnold Robbins to add SVR3 compatibility
+ * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket).
+ * modified by J.T. Conklin for NetBSD.
+ *
+ * This program is in the Public Domain.
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include "bltin.h"
+
+/* test(1) accepts the following grammar:
+	oexpr	::= aexpr | aexpr "-o" oexpr ;
+	aexpr	::= nexpr | nexpr "-a" aexpr ;
+	nexpr	::= primary | "!" primary
+	primary	::= unary-operator operand
+		| operand binary-operator operand
+		| operand
+		| "(" oexpr ")"
+		;
+	unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"|
+		"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
+
+	binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
+			"-nt"|"-ot"|"-ef";
+	operand ::= <any legal UNIX file name>
+*/
+
+enum token {
+	EOI,
+	FILRD,
+	FILWR,
+	FILEX,
+	FILEXIST,
+	FILREG,
+	FILDIR,
+	FILCDEV,
+	FILBDEV,
+	FILFIFO,
+	FILSOCK,
+	FILSYM,
+	FILGZ,
+	FILTT,
+	FILSUID,
+	FILSGID,
+	FILSTCK,
+	FILNT,
+	FILOT,
+	FILEQ,
+	FILUID,
+	FILGID,
+	STREZ,
+	STRNZ,
+	STREQ,
+	STRNE,
+	STRLT,
+	STRGT,
+	INTEQ,
+	INTNE,
+	INTGE,
+	INTGT,
+	INTLE,
+	INTLT,
+	UNOT,
+	BAND,
+	BOR,
+	LPAREN,
+	RPAREN,
+	OPERAND
+};
+
+enum token_types {
+	UNOP,
+	BINOP,
+	BUNOP,
+	BBINOP,
+	PAREN
+};
+
+static struct t_op {
+	const char *op_text;
+	short op_num, op_type;
+} const ops [] = {
+	{"-r",	FILRD,	UNOP},
+	{"-w",	FILWR,	UNOP},
+	{"-x",	FILEX,	UNOP},
+	{"-e",	FILEXIST,UNOP},
+	{"-f",	FILREG,	UNOP},
+	{"-d",	FILDIR,	UNOP},
+	{"-c",	FILCDEV,UNOP},
+	{"-b",	FILBDEV,UNOP},
+	{"-p",	FILFIFO,UNOP},
+	{"-u",	FILSUID,UNOP},
+	{"-g",	FILSGID,UNOP},
+	{"-k",	FILSTCK,UNOP},
+	{"-s",	FILGZ,	UNOP},
+	{"-t",	FILTT,	UNOP},
+	{"-z",	STREZ,	UNOP},
+	{"-n",	STRNZ,	UNOP},
+	{"-h",	FILSYM,	UNOP},		/* for backwards compat */
+	{"-O",	FILUID,	UNOP},
+	{"-G",	FILGID,	UNOP},
+	{"-L",	FILSYM,	UNOP},
+	{"-S",	FILSOCK,UNOP},
+	{"=",	STREQ,	BINOP},
+	{"!=",	STRNE,	BINOP},
+	{"<",	STRLT,	BINOP},
+	{">",	STRGT,	BINOP},
+	{"-eq",	INTEQ,	BINOP},
+	{"-ne",	INTNE,	BINOP},
+	{"-ge",	INTGE,	BINOP},
+	{"-gt",	INTGT,	BINOP},
+	{"-le",	INTLE,	BINOP},
+	{"-lt",	INTLT,	BINOP},
+	{"-nt",	FILNT,	BINOP},
+	{"-ot",	FILOT,	BINOP},
+	{"-ef",	FILEQ,	BINOP},
+	{"!",	UNOT,	BUNOP},
+	{"-a",	BAND,	BBINOP},
+	{"-o",	BOR,	BBINOP},
+	{"(",	LPAREN,	PAREN},
+	{")",	RPAREN,	PAREN},
+	{0,	0,	0}
+};
+
+static char **t_wp;
+static struct t_op const *t_wp_op;
+
+static void syntax(const char *, const char *);
+static int oexpr(enum token);
+static int aexpr(enum token);
+static int nexpr(enum token);
+static int primary(enum token);
+static int binop(void);
+static int filstat(char *, enum token);
+static enum token t_lex(char **);
+static int isoperand(char **);
+static int newerf(const char *, const char *);
+static int olderf(const char *, const char *);
+static int equalf(const char *, const char *);
+#ifdef HAVE_FACCESSAT
+static int test_file_access(const char *, int);
+#else
+static int test_access(const struct stat64 *, int);
+#endif
+
+#ifdef HAVE_FACCESSAT
+# ifdef HAVE_TRADITIONAL_FACCESSAT
+static inline int faccessat_confused_about_superuser(void) { return 1; }
+# else
+static inline int faccessat_confused_about_superuser(void) { return 0; }
+# endif
+#endif
+
+static inline intmax_t getn(const char *s)
+{
+	return atomax10(s);
+}
+
+static const struct t_op *getop(const char *s)
+{
+	const struct t_op *op;
+
+	for (op = ops; op->op_text; op++) {
+		if (strcmp(s, op->op_text) == 0)
+			return op;
+	}
+
+	return NULL;
+}
+
+int
+testcmd(int argc, char **argv)
+{
+	const struct t_op *op;
+	enum token n;
+	int res = 1;
+
+	if (*argv[0] == '[') {
+		if (*argv[--argc] != ']')
+			error("missing ]");
+		argv[argc] = NULL;
+	}
+
+	t_wp_op = NULL;
+
+recheck:
+	argv++;
+	argc--;
+
+	if (argc < 1)
+		return res;
+
+	/*
+	 * POSIX prescriptions: he who wrote this deserves the Nobel
+	 * peace prize.
+	 */
+	switch (argc) {
+	case 3:
+		op = getop(argv[1]);
+		if (op && op->op_type == BINOP) {
+			n = OPERAND;
+			goto eval;
+		}
+		/* fall through */
+
+	case 4:
+		if (!strcmp(argv[0], "(") && !strcmp(argv[argc - 1], ")")) {
+			argv[--argc] = NULL;
+			argv++;
+			argc--;
+		} else if (!strcmp(argv[0], "!")) {
+			res = 0;
+			goto recheck;
+		}
+	}
+
+	n = t_lex(argv);
+
+eval:
+	t_wp = argv;
+	res ^= oexpr(n);
+	argv = t_wp;
+
+	if (argv[0] != NULL && argv[1] != NULL)
+		syntax(argv[0], "unexpected operator");
+
+	return res;
+}
+
+static void
+syntax(const char *op, const char *msg)
+{
+	if (op && *op)
+		error("%s: %s", op, msg);
+	else
+		error("%s", msg);
+}
+
+static int
+oexpr(enum token n)
+{
+	int res = 0;
+
+	for (;;) {
+		res |= aexpr(n);
+		n = t_lex(t_wp + 1);
+		if (n != BOR)
+			break;
+		n = t_lex(t_wp += 2);
+	}
+	return res;
+}
+
+static int
+aexpr(enum token n)
+{
+	int res = 1;
+
+	for (;;) {
+		if (!nexpr(n))
+			res = 0;
+		n = t_lex(t_wp + 1);
+		if (n != BAND)
+			break;
+		n = t_lex(t_wp += 2);
+	}
+	return res;
+}
+
+static int
+nexpr(enum token n)
+{
+	if (n != UNOT)
+		return primary(n);
+
+	n = t_lex(t_wp + 1);
+	if (n != EOI)
+		t_wp++;
+	return !nexpr(n);
+}
+
+static int
+primary(enum token n)
+{
+	enum token nn;
+	int res;
+
+	if (n == EOI)
+		return 0;		/* missing expression */
+	if (n == LPAREN) {
+		if ((nn = t_lex(++t_wp)) == RPAREN)
+			return 0;	/* missing expression */
+		res = oexpr(nn);
+		if (t_lex(++t_wp) != RPAREN)
+			syntax(NULL, "closing paren expected");
+		return res;
+	}
+	if (t_wp_op && t_wp_op->op_type == UNOP) {
+		/* unary expression */
+		if (*++t_wp == NULL)
+			syntax(t_wp_op->op_text, "argument expected");
+		switch (n) {
+		case STREZ:
+			return strlen(*t_wp) == 0;
+		case STRNZ:
+			return strlen(*t_wp) != 0;
+		case FILTT:
+			return isatty(getn(*t_wp));
+#ifdef HAVE_FACCESSAT
+		case FILRD:
+			return test_file_access(*t_wp, R_OK);
+		case FILWR:
+			return test_file_access(*t_wp, W_OK);
+		case FILEX:
+			return test_file_access(*t_wp, X_OK);
+#endif
+		default:
+			return filstat(*t_wp, n);
+		}
+	}
+
+	if (t_lex(t_wp + 1), t_wp_op && t_wp_op->op_type == BINOP) {
+		return binop();
+	}
+
+	return strlen(*t_wp) > 0;
+}
+
+static int
+binop(void)
+{
+	const char *opnd1, *opnd2;
+	struct t_op const *op;
+
+	opnd1 = *t_wp;
+	(void) t_lex(++t_wp);
+	op = t_wp_op;
+
+	if ((opnd2 = *++t_wp) == (char *)0)
+		syntax(op->op_text, "argument expected");
+
+	switch (op->op_num) {
+	default:
+#ifdef DEBUG
+		abort();
+		/* NOTREACHED */
+#endif
+	case STREQ:
+		return strcmp(opnd1, opnd2) == 0;
+	case STRNE:
+		return strcmp(opnd1, opnd2) != 0;
+	case STRLT:
+		return strcmp(opnd1, opnd2) < 0;
+	case STRGT:
+		return strcmp(opnd1, opnd2) > 0;
+	case INTEQ:
+		return getn(opnd1) == getn(opnd2);
+	case INTNE:
+		return getn(opnd1) != getn(opnd2);
+	case INTGE:
+		return getn(opnd1) >= getn(opnd2);
+	case INTGT:
+		return getn(opnd1) > getn(opnd2);
+	case INTLE:
+		return getn(opnd1) <= getn(opnd2);
+	case INTLT:
+		return getn(opnd1) < getn(opnd2);
+	case FILNT:
+		return newerf (opnd1, opnd2);
+	case FILOT:
+		return olderf (opnd1, opnd2);
+	case FILEQ:
+		return equalf (opnd1, opnd2);
+	}
+}
+
+static int
+filstat(char *nm, enum token mode)
+{
+	struct stat64 s;
+
+	if (mode == FILSYM ? lstat64(nm, &s) : stat64(nm, &s))
+		return 0;
+
+	switch (mode) {
+#ifndef HAVE_FACCESSAT
+	case FILRD:
+		return test_access(&s, R_OK);
+	case FILWR:
+		return test_access(&s, W_OK);
+	case FILEX:
+		return test_access(&s, X_OK);
+#endif
+	case FILEXIST:
+		return 1;
+	case FILREG:
+		return S_ISREG(s.st_mode);
+	case FILDIR:
+		return S_ISDIR(s.st_mode);
+	case FILCDEV:
+		return S_ISCHR(s.st_mode);
+	case FILBDEV:
+		return S_ISBLK(s.st_mode);
+	case FILFIFO:
+		return S_ISFIFO(s.st_mode);
+	case FILSOCK:
+		return S_ISSOCK(s.st_mode);
+	case FILSYM:
+		return S_ISLNK(s.st_mode);
+	case FILSUID:
+		return (s.st_mode & S_ISUID) != 0;
+	case FILSGID:
+		return (s.st_mode & S_ISGID) != 0;
+	case FILSTCK:
+		return (s.st_mode & S_ISVTX) != 0;
+	case FILGZ:
+		return !!s.st_size;
+	case FILUID:
+		return s.st_uid == geteuid();
+	case FILGID:
+		return s.st_gid == getegid();
+	default:
+		return 1;
+	}
+}
+
+static enum token t_lex(char **tp)
+{
+	struct t_op const *op;
+	char *s = *tp;
+
+	if (s == 0) {
+		t_wp_op = (struct t_op *)0;
+		return EOI;
+	}
+
+	op = getop(s);
+	if (op && !(op->op_type == UNOP && isoperand(tp)) &&
+	    !(op->op_num == LPAREN && !tp[1])) {
+		t_wp_op = op;
+		return op->op_num;
+	}
+
+	t_wp_op = (struct t_op *)0;
+	return OPERAND;
+}
+
+static int isoperand(char **tp)
+{
+	struct t_op const *op;
+	char *s;
+
+	if (!(s = tp[1]))
+		return 1;
+	if (!tp[2])
+		return 0;
+
+	op = getop(s);
+	return op && op->op_type == BINOP;
+}
+
+static int
+newerf (const char *f1, const char *f2)
+{
+	struct stat64 b1, b2;
+
+#ifdef HAVE_ST_MTIM
+	return (stat64(f1, &b1) == 0 &&
+		stat64(f2, &b2) == 0 &&
+		( b1.st_mtim.tv_sec > b2.st_mtim.tv_sec ||
+		 (b1.st_mtim.tv_sec == b2.st_mtim.tv_sec && (b1.st_mtim.tv_nsec > b2.st_mtim.tv_nsec )))
+	);
+#else
+	return (stat64(f1, &b1) == 0 &&
+		stat64(f2, &b2) == 0 &&
+		b1.st_mtime > b2.st_mtime);
+#endif
+}
+
+static int
+olderf (const char *f1, const char *f2)
+{
+	struct stat64 b1, b2;
+
+#ifdef HAVE_ST_MTIM
+	return (stat64(f1, &b1) == 0 &&
+		stat64(f2, &b2) == 0 &&
+		(b1.st_mtim.tv_sec < b2.st_mtim.tv_sec ||
+		 (b1.st_mtim.tv_sec == b2.st_mtim.tv_sec && (b1.st_mtim.tv_nsec < b2.st_mtim.tv_nsec )))
+	);
+#else
+	return (stat64(f1, &b1) == 0 &&
+		stat64(f2, &b2) == 0 &&
+		b1.st_mtime < b2.st_mtime);
+#endif
+}
+
+static int
+equalf (const char *f1, const char *f2)
+{
+	struct stat64 b1, b2;
+
+	return (stat64(f1, &b1) == 0 &&
+		stat64(f2, &b2) == 0 &&
+		b1.st_dev == b2.st_dev &&
+		b1.st_ino == b2.st_ino);
+}
+
+#ifdef HAVE_FACCESSAT
+static int has_exec_bit_set(const char *path)
+{
+	struct stat64 st;
+
+	if (stat64(path, &st))
+		return 0;
+	return st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH);
+}
+
+static int test_file_access(const char *path, int mode)
+{
+	if (faccessat_confused_about_superuser() &&
+	    mode == X_OK && geteuid() == 0 && !has_exec_bit_set(path))
+		return 0;
+	return !faccessat(AT_FDCWD, path, mode, AT_EACCESS);
+}
+#else	/* HAVE_FACCESSAT */
+/*
+ * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits,
+ * not use access():
+ *
+ *	True shall indicate only that the write flag is on.  The file is not
+ *	writable on a read-only file system even if this test indicates true.
+ *
+ * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only:
+ *
+ *	True shall indicate that permission to read from file will be granted,
+ *	as defined in "File Read, Write, and Creation".
+ *
+ * and that section says:
+ *
+ *	When a file is to be read or written, the file shall be opened with an
+ *	access mode corresponding to the operation to be performed.  If file
+ *	access permissions deny access, the requested operation shall fail.
+ *
+ * and of course access permissions are described as one might expect:
+ *
+ *     * If a process has the appropriate privilege:
+ *
+ *        * If read, write, or directory search permission is requested,
+ *          access shall be granted.
+ *
+ *        * If execute permission is requested, access shall be granted if
+ *          execute permission is granted to at least one user by the file
+ *          permission bits or by an alternate access control mechanism;
+ *          otherwise, access shall be denied.
+ *
+ *   * Otherwise:
+ *
+ *        * The file permission bits of a file contain read, write, and
+ *          execute/search permissions for the file owner class, file group
+ *          class, and file other class.
+ *
+ *        * Access shall be granted if an alternate access control mechanism
+ *          is not enabled and the requested access permission bit is set for
+ *          the class (file owner class, file group class, or file other class)
+ *          to which the process belongs, or if an alternate access control
+ *          mechanism is enabled and it allows the requested access; otherwise,
+ *          access shall be denied.
+ *
+ * and when I first read this I thought:  surely we can't go about using
+ * open(O_WRONLY) to try this test!  However the POSIX 1003.1-2001 Rationale
+ * section for test does in fact say:
+ *
+ *	On historical BSD systems, test -w directory always returned false
+ *	because test tried to open the directory for writing, which always
+ *	fails.
+ *
+ * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX
+ * System III, and thus presumably also for BSD up to and including 4.3.
+ *
+ * Secondly I remembered why using open() and/or access() are bogus.  They
+ * don't work right for detecting read and write permissions bits when called
+ * by root.
+ *
+ * Interestingly the 'test' in 4.4BSD was closer to correct (as per
+ * 1003.2-1992) and it was implemented efficiently with stat() instead of
+ * open().
+ *
+ * This was apparently broken in NetBSD around about 1994/06/30 when the old
+ * 4.4BSD implementation was replaced with a (arguably much better coded)
+ * implementation derived from pdksh.
+ *
+ * Note that modern pdksh is yet different again, but still not correct, at
+ * least not w.r.t. 1003.2-1992.
+ *
+ * As I think more about it and read more of the related IEEE docs I don't like
+ * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all.  I very
+ * much prefer the original wording in 1003.2-1992.  It is much more useful,
+ * and so that's what I've implemented.
+ *
+ * (Note that a strictly conforming implementation of 1003.1-2001 is in fact
+ * totally useless for the case in question since its 'test -w' and 'test -r'
+ * can never fail for root for any existing files, i.e. files for which 'test
+ * -e' succeeds.)
+ *
+ * The rationale for 1003.1-2001 suggests that the wording was "clarified" in
+ * 1003.1-2001 to align with the 1003.2b draft.  1003.2b Draft 12 (July 1999),
+ * which is the latest copy I have, does carry the same suggested wording as is
+ * in 1003.1-2001, with its rationale saying:
+ *
+ * 	This change is a clarification and is the result of interpretation
+ * 	request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992.
+ *
+ * That interpretation can be found here:
+ *
+ *   http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html
+ *
+ * Not terribly helpful, unfortunately.  I wonder who that fence sitter was.
+ *
+ * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the
+ * PASC interpretation and appear to be gone against at least one widely used
+ * implementation (namely 4.4BSD).  The problem is that for file access by root
+ * this means that if test '-r' and '-w' are to behave as if open() were called
+ * then there's no way for a shell script running as root to check if a file
+ * has certain access bits set other than by the grotty means of interpreting
+ * the output of 'ls -l'.  This was widely considered to be a bug in V7's
+ * "test" and is, I believe, one of the reasons why direct use of access() was
+ * avoided in some more recent implementations!
+ *
+ * I have always interpreted '-r' to match '-w' and '-x' as per the original
+ * wording in 1003.2-1992, not the other way around.  I think 1003.2b goes much
+ * too far the wrong way without any valid rationale and that it's best if we
+ * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of
+ * open() since we already know very well how it will work -- existance of the
+ * file is all that matters to open() for root.
+ *
+ * Unfortunately the SVID is no help at all (which is, I guess, partly why
+ * we're in this mess in the first place :-).
+ *
+ * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use
+ * access(name, 2) even though it also goes to much greater lengths for '-x'
+ * matching the 1003.2-1992 definition (which is no doubt where that definition
+ * came from).
+ *
+ * The ksh93 implementation uses access() for '-r' and '-w' if
+ * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root.
+ * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b).
+ */
+static int test_access(const struct stat64 *sp, int stmode)
+{
+	gid_t *groups;
+	register int n;
+	uid_t euid;
+	int maxgroups;
+
+	/*
+	 * I suppose we could use access() if not running as root and if we are
+	 * running with ((euid == uid) && (egid == gid)), but we've already
+	 * done the stat() so we might as well just test the permissions
+	 * directly instead of asking the kernel to do it....
+	 */
+	euid = geteuid();
+	if (euid == 0) {
+		if (stmode != X_OK)
+			return 1;
+
+		/* any bit is good enough */
+		stmode = (stmode << 6) | (stmode << 3) | stmode;
+	} else if (sp->st_uid == euid)
+		stmode <<= 6;
+	else if (sp->st_gid == getegid())
+		stmode <<= 3;
+	else {
+		/* XXX stolen almost verbatim from ksh93.... */
+		/* on some systems you can be in several groups */
+		maxgroups = getgroups(0, NULL);
+		groups = stalloc(maxgroups * sizeof(*groups));
+		n = getgroups(maxgroups, groups);
+		while (--n >= 0) {
+			if (groups[n] == sp->st_gid) {
+				stmode <<= 3;
+				break;
+			}
+		}
+	}
+
+	return sp->st_mode & stmode;
+}
+#endif	/* HAVE_FACCESSAT */
diff --git a/bin/dash/src/bltin/times.c b/bin/dash/src/bltin/times.c
new file mode 100644
index 00000000..1166a68e
--- /dev/null
+++ b/bin/dash/src/bltin/times.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1999 Herbert Xu <herbert@gondor.apana.org.au>
+ * This file contains code for the times builtin.
+ */
+
+#include <sys/times.h>
+#include <unistd.h>
+#ifdef USE_GLIBC_STDIO
+#include <stdio.h>
+#else
+#include "bltin.h"
+#endif
+#include "system.h"
+
+int timescmd() {
+	struct tms buf;
+	long int clk_tck = sysconf(_SC_CLK_TCK);
+	int mutime, mstime, mcutime, mcstime;
+	double utime, stime, cutime, cstime;
+
+	times(&buf);
+
+	utime = (double)buf.tms_utime / clk_tck;
+	mutime = utime / 60;
+	utime -= mutime * 60.0;
+
+	stime = (double)buf.tms_stime / clk_tck;
+	mstime = stime / 60;
+	stime -= mstime * 60.0;
+
+	cutime = (double)buf.tms_cutime / clk_tck;
+	mcutime = cutime / 60;
+	cutime -= mcutime * 60.0;
+
+	cstime = (double)buf.tms_cstime / clk_tck;
+	mcstime = cstime / 60;
+	cstime -= mcstime * 60.0;
+
+	printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n", mutime, utime, mstime, stime,
+	       mcutime, cutime, mcstime, cstime);
+	return 0;
+}
diff --git a/bin/dash/src/builtins.def.in b/bin/dash/src/builtins.def.in
new file mode 100644
index 00000000..95e420cc
--- /dev/null
+++ b/bin/dash/src/builtins.def.in
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)builtins.def	8.4 (Berkeley) 5/4/95
+ */
+
+/*
+ * This file lists all the builtin commands.  The first column is the name
+ * of a C routine.
+ * The -a flag specifies that this is a posix 'assignment builtin' command.
+ * The -s flag specifies that this is a posix 'special builtin' command.
+ * The -u flag specifies that this is a posix 'standard utility'.
+ * The -n flag specifies that this command has a special entry point.
+ * The rest of the line specifies the command name or names used to run
+ * the command.
+ */
+
+#ifndef JOBS
+#define JOBS 1
+#endif
+
+#if JOBS
+bgcmd		-u bg
+fgcmd		-u fg
+#endif
+
+#ifndef SMALL
+histcmd		-u fc
+#endif
+
+breakcmd	-s break -s continue
+cdcmd		-u cd chdir
+commandcmd	-u command
+dotcmd		-s .
+echocmd		echo
+evalcmd		-ns eval
+execcmd		-s exec
+exitcmd		-s exit
+exportcmd	-as export -as readonly
+falsecmd	-u false
+getoptscmd	-u getopts
+hashcmd		-u hash
+jobscmd		-u jobs
+localcmd	-as local
+printfcmd	printf
+pwdcmd		-u pwd
+readcmd		-u read
+returncmd	-s return
+setcmd		-s set
+shiftcmd	-s shift
+timescmd	-s times
+trapcmd		-s trap
+truecmd		-s : -u true
+typecmd		-u type
+umaskcmd	-u umask
+unaliascmd	-u unalias
+unsetcmd	-s unset
+waitcmd		-u wait
+aliascmd	-au alias
+#ifdef HAVE_GETRLIMIT
+ulimitcmd	-u ulimit
+#endif
+testcmd		test [
+killcmd		-u kill
diff --git a/bin/dash/src/cd.c b/bin/dash/src/cd.c
new file mode 100644
index 00000000..1ef1dc56
--- /dev/null
+++ b/bin/dash/src/cd.c
@@ -0,0 +1,332 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+#endif
+
+/*
+ * The cd and pwd commands.
+ */
+
+#include "shell.h"
+#include "var.h"
+#include "nodes.h"	/* for jobs.h */
+#include "jobs.h"
+#include "options.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "exec.h"
+#include "redir.h"
+#include "main.h"
+#include "mystring.h"
+#include "show.h"
+#include "cd.h"
+
+#define CD_PHYSICAL 1
+#define CD_PRINT 2
+
+STATIC int docd(const char *, int);
+STATIC const char *updatepwd(const char *);
+STATIC char *getpwd(void);
+STATIC int cdopt(void);
+
+STATIC char *curdir = nullstr;		/* current working directory */
+STATIC char *physdir = nullstr;		/* physical working directory */
+
+STATIC int
+cdopt()
+{
+	int flags = 0;
+	int i, j;
+
+	j = 'L';
+	while ((i = nextopt("LP"))) {
+		if (i != j) {
+			flags ^= CD_PHYSICAL;
+			j = i;
+		}
+	}
+
+	return flags;
+}
+
+int
+cdcmd(int argc, char **argv)
+{
+	const char *dest;
+	const char *path;
+	const char *p;
+	char c;
+	struct stat64 statb;
+	int flags;
+	int len;
+
+	flags = cdopt();
+	dest = *argptr;
+	if (!dest)
+		dest = bltinlookup(homestr);
+	else if (dest[0] == '-' && dest[1] == '\0') {
+		dest = bltinlookup("OLDPWD");
+		flags |= CD_PRINT;
+	}
+	if (!dest)
+		dest = nullstr;
+	if (*dest == '/')
+		goto step6;
+	if (*dest == '.') {
+		c = dest[1];
+dotdot:
+		switch (c) {
+		case '\0':
+		case '/':
+			goto step6;
+		case '.':
+			c = dest[2];
+			if (c != '.')
+				goto dotdot;
+		}
+	}
+	if (!*dest)
+		dest = ".";
+	path = bltinlookup("CDPATH");
+	while (p = path, (len = padvance_magic(&path, dest, 0)) >= 0) {
+		c = *p;
+		p = stalloc(len);
+
+		if (stat64(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
+			if (c && c != ':')
+				flags |= CD_PRINT;
+docd:
+			if (!docd(p, flags))
+				goto out;
+			goto err;
+		}
+	}
+
+step6:
+	p = dest;
+	goto docd;
+
+err:
+	sh_error("can't cd to %s", dest);
+	/* NOTREACHED */
+out:
+	if (flags & CD_PRINT)
+		out1fmt(snlfmt, curdir);
+	return 0;
+}
+
+
+/*
+ * Actually do the chdir.  We also call hashcd to let the routines in exec.c
+ * know that the current directory has changed.
+ */
+
+STATIC int
+docd(const char *dest, int flags)
+{
+	const char *dir = 0;
+	int err;
+
+	TRACE(("docd(\"%s\", %d) called\n", dest, flags));
+
+	INTOFF;
+	if (!(flags & CD_PHYSICAL)) {
+		dir = updatepwd(dest);
+		if (dir)
+			dest = dir;
+	}
+	err = chdir(dest);
+	if (err)
+		goto out;
+	setpwd(dir, 1);
+	hashcd();
+out:
+	INTON;
+	return err;
+}
+
+
+/*
+ * Update curdir (the name of the current directory) in response to a
+ * cd command.
+ */
+
+STATIC const char *
+updatepwd(const char *dir)
+{
+	char *new;
+	char *p;
+	char *cdcomppath;
+	const char *lim;
+
+#ifdef __CYGWIN__
+	/* On cygwin, thanks to drive letters, some absolute paths do
+	   not begin with slash; but cygwin includes a function that
+	   forces normalization to the posix form */
+	char pathbuf[PATH_MAX];
+	if (cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_RELATIVE, dir, pathbuf,
+			     sizeof(pathbuf)) < 0)
+		sh_error("can't normalize %s", dir);
+	dir = pathbuf;
+#endif
+
+	cdcomppath = sstrdup(dir);
+	STARTSTACKSTR(new);
+	if (*dir != '/') {
+		if (curdir == nullstr)
+			return 0;
+		new = stputs(curdir, new);
+	}
+	new = makestrspace(strlen(dir) + 2, new);
+	lim = stackblock() + 1;
+	if (*dir != '/') {
+		if (new[-1] != '/')
+			USTPUTC('/', new);
+		if (new > lim && *lim == '/')
+			lim++;
+	} else {
+		USTPUTC('/', new);
+		cdcomppath++;
+		if (dir[1] == '/' && dir[2] != '/') {
+			USTPUTC('/', new);
+			cdcomppath++;
+			lim++;
+		}
+	}
+	p = strtok(cdcomppath, "/");
+	while (p) {
+		switch(*p) {
+		case '.':
+			if (p[1] == '.' && p[2] == '\0') {
+				while (new > lim) {
+					STUNPUTC(new);
+					if (new[-1] == '/')
+						break;
+				}
+				break;
+			} else if (p[1] == '\0')
+				break;
+			/* fall through */
+		default:
+			new = stputs(p, new);
+			USTPUTC('/', new);
+		}
+		p = strtok(0, "/");
+	}
+	if (new > lim)
+		STUNPUTC(new);
+	*new = 0;
+	return stackblock();
+}
+
+
+/*
+ * Find out what the current directory is. If we already know the current
+ * directory, this routine returns immediately.
+ */
+inline
+STATIC char *
+getpwd()
+{
+#ifdef __GLIBC__
+	char *dir = getcwd(0, 0);
+
+	if (dir)
+		return dir;
+#else
+	char buf[PATH_MAX];
+
+	if (getcwd(buf, sizeof(buf)))
+		return savestr(buf);
+#endif
+
+	sh_warnx("getcwd() failed: %s", strerror(errno));
+	return nullstr;
+}
+
+int
+pwdcmd(int argc, char **argv)
+{
+	int flags;
+	const char *dir = curdir;
+
+	flags = cdopt();
+	if (flags) {
+		if (physdir == nullstr)
+			setpwd(dir, 0);
+		dir = physdir;
+	}
+	out1fmt(snlfmt, dir);
+	return 0;
+}
+
+void
+setpwd(const char *val, int setold)
+{
+	char *oldcur, *dir;
+
+	oldcur = dir = curdir;
+
+	if (setold) {
+		setvar("OLDPWD", oldcur, VEXPORT);
+	}
+	INTOFF;
+	if (physdir != nullstr) {
+		if (physdir != oldcur)
+			free(physdir);
+		physdir = nullstr;
+	}
+	if (oldcur == val || !val) {
+		char *s = getpwd();
+		physdir = s;
+		if (!val)
+			dir = s;
+	} else
+		dir = savestr(val);
+	if (oldcur != dir && oldcur != nullstr) {
+		free(oldcur);
+	}
+	curdir = dir;
+	INTON;
+	setvar("PWD", dir, VEXPORT);
+}
diff --git a/bin/dash/src/cd.h b/bin/dash/src/cd.h
new file mode 100644
index 00000000..87631619
--- /dev/null
+++ b/bin/dash/src/cd.h
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 1995
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ */
+
+int	cdcmd(int, char **);
+int	pwdcmd(int, char **);
+void	setpwd(const char *, int);
diff --git a/bin/dash/src/dash.1 b/bin/dash/src/dash.1
new file mode 100644
index 00000000..9bc51cd6
--- /dev/null
+++ b/bin/dash/src/dash.1
@@ -0,0 +1,2361 @@
+.\" Copyright (c) 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\" Copyright (c) 1997-2005
+.\"	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Kenneth Almquist.
+.\"
+.\" 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.
+.\" 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"	@(#)sh.1	8.6 (Berkeley) 5/4/95
+.\"
+.Dd December 22, 2020
+.Os
+.Dt DASH 1
+.Sh NAME
+.Nm dash
+.Nd command interpreter (shell)
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Op Ar command_file Oo Ar argument ... Oc
+.Ek
+.Nm
+.Fl c
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Ar command_string
+.Op Ar command_name Oo Ar argument ... Oc
+.Ek
+.Nm
+.Fl s
+.Bk -words
+.Op Fl aCefnuvxIimqVEb
+.Op Cm +aCefnuvxIimqVEb
+.Ek
+.Bk -words
+.Op Fl o Ar option_name
+.Op Cm +o Ar option_name
+.Ek
+.Bk -words
+.Op Ar argument ...
+.Ek
+.Sh DESCRIPTION
+.Nm
+is the standard command interpreter for the system.
+The current version of
+.Nm
+is in the process of being changed to conform with the
+.Tn POSIX
+1003.2 and 1003.2a specifications for the shell.
+This version has many
+features which make it appear similar in some respects to the Korn shell,
+but it is not a Korn shell clone (see
+.Xr ksh 1 ) .
+Only features designated by
+.Tn POSIX ,
+plus a few Berkeley extensions, are being incorporated into this shell.
+This man page is not intended
+to be a tutorial or a complete specification of the shell.
+.Ss Overview
+The shell is a command that reads lines from either a file or the
+terminal, interprets them, and generally executes other commands.
+It is the program that is running when a user logs into the system
+(although a user can select a different shell with the
+.Xr chsh 1
+command).
+The shell implements a language that has flow control
+constructs, a macro facility that provides a variety of features in
+addition to data storage, along with built in history and line editing
+capabilities.
+It incorporates many features to aid interactive use and
+has the advantage that the interpretative language is common to both
+interactive and non-interactive use (shell scripts).
+That is, commands
+can be typed directly to the running shell or can be put into a file and
+the file can be executed directly by the shell.
+.Ss Invocation
+If no args are present and if the standard input of the shell
+is connected to a terminal (or if the
+.Fl i
+flag is set),
+and the
+.Fl c
+option is not present, the shell is considered an interactive shell.
+An interactive shell generally prompts before each command and handles
+programming and command errors differently (as described below).
+When first starting,
+the shell inspects argument 0, and if it begins with a dash
+.Sq - ,
+the shell is also considered
+a login shell.
+This is normally done automatically by the system
+when the user first logs in.
+A login shell first reads commands
+from the files
+.Pa /etc/profile
+and
+.Pa .profile
+if they exist.
+If the environment variable
+.Ev ENV
+is set on entry to an interactive shell, or is set in the
+.Pa .profile
+of a login shell, the shell next reads
+commands from the file named in
+.Ev ENV .
+Therefore, a user should place commands that are to be executed only at
+login time in the
+.Pa .profile
+file, and commands that are executed for every interactive shell inside the
+.Ev ENV
+file.
+To set the
+.Ev ENV
+variable to some file, place the following line in your
+.Pa .profile
+of your home directory
+.Pp
+.Dl ENV=$HOME/.shinit; export ENV
+.Pp
+substituting for
+.Dq .shinit
+any filename you wish.
+.Pp
+If command line arguments besides the options have been specified, then
+the shell treats the first argument as the name of a file from which to
+read commands (a shell script), and the remaining arguments are set as the
+positional parameters of the shell ($1, $2, etc).
+Otherwise, the shell
+reads commands from its standard input.
+.Ss Argument List Processing
+All of the single letter options that have a corresponding name can be
+used as an argument to the
+.Fl o
+option.
+The set
+.Fl o
+name is provided next to the single letter option in
+the description below.
+Specifying a dash
+.Dq -
+turns the option on, while using a plus
+.Dq +
+disables the option.
+The following options can be set from the command line or
+with the
+.Ic set
+builtin (described later).
+.Bl -tag -width aaaallexportfoo -offset indent
+.It Fl a Em allexport
+Export all variables assigned to.
+.It Fl c
+Read commands from the
+.Ar command_string
+operand instead of from the standard input.
+Special parameter 0 will be set from the
+.Ar command_name
+operand and the positional parameters ($1, $2, etc.)
+set from the remaining argument operands.
+.It Fl C Em noclobber
+Don't overwrite existing files with
+.Dq \*[Gt] .
+.It Fl e Em errexit
+If not interactive, exit immediately if any untested command fails.
+The exit status of a command is considered to be
+explicitly tested if the command is used to control an
+.Ic if ,
+.Ic elif ,
+.Ic while ,
+or
+.Ic until ;
+or if the command is the left hand operand of an
+.Dq &&
+or
+.Dq ||
+operator.
+.It Fl f Em noglob
+Disable pathname expansion.
+.It Fl n Em noexec
+If not interactive, read commands but do not execute them.
+This is useful for checking the syntax of shell scripts.
+.It Fl u Em nounset
+Write a message to standard error when attempting to expand a variable
+that is not set, and if the shell is not interactive, exit immediately.
+.It Fl v Em verbose
+The shell writes its input to standard error as it is read.
+Useful for debugging.
+.It Fl x Em xtrace
+Write each command to standard error (preceded by a
+.Sq +\  )
+before it is executed.
+Useful for debugging.
+.It Fl I Em ignoreeof
+Ignore EOF's from input when interactive.
+.It Fl i Em interactive
+Force the shell to behave interactively.
+.It Fl l
+Make dash act as if it had been invoked as a login shell.
+.It Fl m Em monitor
+Turn on job control (set automatically when interactive).
+.It Fl s Em stdin
+Read commands from standard input (set automatically if no file arguments
+are present).
+This option has no effect when set after the shell has
+already started running (i.e. with
+.Ic set ) .
+.It Fl V Em vi
+Enable the built-in
+.Xr vi 1
+command line editor (disables
+.Fl E
+if it has been set).
+.It Fl E Em emacs
+Enable the built-in
+.Xr emacs 1
+command line editor (disables
+.Fl V
+if it has been set).
+.It Fl b Em notify
+Enable asynchronous notification of background job completion.
+(UNIMPLEMENTED for 4.4alpha)
+.El
+.Ss Lexical Structure
+The shell reads input in terms of lines from a file and breaks it up into
+words at whitespace (blanks and tabs), and at certain sequences of
+characters that are special to the shell called
+.Dq operators .
+There are two types of operators: control operators and redirection
+operators (their meaning is discussed later).
+Following is a list of operators:
+.Bl -ohang -offset indent
+.It "Control operators:"
+.Dl &  &&  \&(  \&)  \&;  ;; | || \*[Lt]newline\*[Gt]
+.It "Redirection operators:"
+.Dl \*[Lt]  \*[Gt]  \*[Gt]|  \*[Lt]\*[Lt]  \*[Gt]\*[Gt]  \*[Lt]&  \*[Gt]&  \*[Lt]\*[Lt]-  \*[Lt]\*[Gt]
+.El
+.Ss Quoting
+Quoting is used to remove the special meaning of certain characters or
+words to the shell, such as operators, whitespace, or keywords.
+There are three types of quoting: matched single quotes,
+matched double quotes, and backslash.
+.Ss Backslash
+A backslash preserves the literal meaning of the following
+character, with the exception of
+.Aq newline .
+A backslash preceding a
+.Aq newline
+is treated as a line continuation.
+.Ss Single Quotes
+Enclosing characters in single quotes preserves the literal meaning of all
+the characters (except single quotes, making it impossible to put
+single-quotes in a single-quoted string).
+.Ss Double Quotes
+Enclosing characters within double quotes preserves the literal
+meaning of all characters except dollarsign
+.Pq $ ,
+backquote
+.Pq ` ,
+and backslash
+.Pq \e .
+The backslash inside double quotes is historically weird, and serves to
+quote only the following characters:
+.Dl $  `  \*q  \e  \*[Lt]newline\*[Gt] .
+Otherwise it remains literal.
+.Ss Reserved Words
+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:
+.Bl -column while while while while while -offset indent
+.It ! Ta elif Ta fi Ta while Ta case
+.It else Ta for Ta then Ta { Ta }
+.It do Ta done Ta until Ta if Ta esac
+.El
+.Pp
+Their meaning is discussed later.
+.Ss Aliases
+An alias is a name and corresponding value set using the
+.Xr alias 1
+builtin command.
+Whenever a reserved word may occur (see above),
+and after checking for reserved words, 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
+.Dq lf
+with the value
+.Dq "ls -F" ,
+then the input:
+.Pp
+.Dl lf foobar Aq return
+.Pp
+would become
+.Pp
+.Dl ls -F foobar Aq return
+.Pp
+Aliases provide a convenient way for naive users to create shorthands for
+commands without having to learn how to create functions with arguments.
+They can also be used to create lexically obscure code.
+This use is discouraged.
+.Ss Commands
+The shell interprets the words it reads according to a language, the
+specification of which is outside the scope of this man page (refer to the
+BNF in the
+.Tn POSIX
+1003.2 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 simple command.
+Otherwise, a complex
+command or some other special construct may have been recognized.
+.Ss Simple Commands
+If a simple command has been recognized, the shell performs
+the following actions:
+.Bl -enum -offset indent
+.It
+Leading words of the form
+.Dq name=value
+are stripped off and assigned to the environment of the simple command.
+Redirection operators and their arguments (as described below) are
+stripped off and saved for processing.
+.It
+The remaining words are expanded as described in
+the section called
+.Dq Expansions ,
+and the first remaining word is considered the command name and the
+command is located.
+The remaining words are considered the arguments of the command.
+If no command name resulted, then the
+.Dq name=value
+variable assignments recognized in item 1 affect the current shell.
+.It
+Redirections are performed as described in the next section.
+.El
+.Ss Redirections
+Redirections are used to change where a command reads its input or sends
+its output.
+In general, redirections open, close, or duplicate an
+existing reference to a file.
+The overall format used for redirection is:
+.Pp
+.Dl [n] Va redir-op Ar file
+.Pp
+where
+.Va redir-op
+is one of the redirection operators mentioned previously.
+Following is a list of the possible redirections.
+The
+.Bq n
+is an optional number between 0 and 9, as in
+.Sq 3
+(not
+.Sq Bq 3 ) ,
+that refers to a file descriptor.
+.Bl -tag -width aaabsfiles -offset indent
+.It [n] Ns \*[Gt] file
+Redirect standard output (or n) to file.
+.It [n] Ns \*[Gt]| file
+Same, but override the
+.Fl C
+option.
+.It [n] Ns \*[Gt]\*[Gt] file
+Append standard output (or n) to file.
+.It [n] Ns \*[Lt] file
+Redirect standard input (or n) from file.
+.It [n1] Ns \*[Lt]& Ns n2
+Copy file descriptor n2 as stdout (or fd n1).
+fd n2.
+.It [n] Ns \*[Lt]&-
+Close standard input (or n).
+.It [n1] Ns \*[Gt]& Ns n2
+Copy file descriptor n2 as stdin (or fd n1).
+fd n2.
+.It [n] Ns \*[Gt]&-
+Close standard output (or n).
+.It [n] Ns \*[Lt]\*[Gt] file
+Open file for reading and writing on standard input (or n).
+.El
+.Pp
+The following redirection is often called a
+.Dq here-document .
+.Bl -item -offset indent
+.It
+.Li [n]\*[Lt]\*[Lt] delimiter
+.Dl here-doc-text ...
+.Li delimiter
+.El
+.Pp
+All the text on successive lines up to the delimiter is saved away and
+made available to the command on standard input, or file descriptor n if
+it is specified.
+If the delimiter as specified on the initial line is
+quoted, then the here-doc-text is treated literally, otherwise the text is
+subjected to parameter expansion, command substitution, and arithmetic
+expansion (as described in the section on
+.Dq Expansions ) .
+If the operator is
+.Dq \*[Lt]\*[Lt]-
+instead of
+.Dq \*[Lt]\*[Lt] ,
+then leading tabs in the here-doc-text are stripped.
+.Ss Search and Execution
+There are three types of commands: shell functions, builtin commands, and
+normal programs -- and the command is searched for (by name) in that order.
+They each are executed in a different way.
+.Pp
+When a shell function is executed, all of the shell positional parameters
+(except $0, which remains unchanged) are set to the arguments of the shell
+function.
+The variables which are explicitly placed in the environment of
+the command (by placing assignments to them before the function name) are
+made local to the function and are set to the values given.
+Then the command given in the function definition is executed.
+The positional parameters are restored to their original values
+when the command completes.
+This all occurs within the current shell.
+.Pp
+Shell builtins are executed internally to the shell, without spawning a
+new process.
+.Pp
+Otherwise, if the command name doesn't match a function or builtin, the
+command is searched for as a normal program in the file system (as
+described in the next section).
+When a normal program is executed, the shell runs the program,
+passing the arguments and the environment to the program.
+If the program is not a normal executable file (i.e., if it does
+not begin with the "magic number" whose
+.Tn ASCII
+representation is "#!", so
+.Xr execve 2
+returns
+.Er ENOEXEC
+then) the shell will interpret the program in a subshell.
+The child shell will reinitialize itself in this case,
+so that the effect will be as if a
+new shell had been invoked to handle the ad-hoc shell script, except that
+the location of hashed commands located in the parent shell will be
+remembered by the child.
+.Pp
+Note that previous versions of this document and the source code itself
+misleadingly and sporadically refer to a shell script without a magic
+number as a "shell procedure".
+.Ss Path Search
+When locating a command, the shell first looks to see if it has a shell
+function by that name.
+Then it looks for a builtin command by that name.
+If a builtin command is not found, one of two things happen:
+.Bl -enum
+.It
+Command names containing a slash are simply executed without performing
+any searches.
+.It
+The shell searches each entry in
+.Ev PATH
+in turn for the command.
+The value of the
+.Ev PATH
+variable should be a series of entries separated by colons.
+Each entry consists of a directory name.
+The current directory may be indicated
+implicitly by an empty directory name, or explicitly by a single period.
+.El
+.Ss Command Exit Status
+Each command has an exit status that can influence the behaviour
+of other shell commands.
+The paradigm is that a command exits
+with zero for normal or success, and non-zero for failure,
+error, or a false indication.
+The man page for each command
+should indicate the various exit codes and what they mean.
+Additionally, the builtin commands return exit codes, as does
+an executed shell function.
+.Pp
+If a command consists entirely of variable assignments then the
+exit status of the command is that of the last command substitution
+if any, otherwise 0.
+.Ss Complex Commands
+Complex commands are combinations of simple commands with control
+operators or reserved words, together creating a larger complex command.
+More generally, a command is one of the following:
+.Bl -bullet
+.It
+simple command
+.It
+pipeline
+.It
+list or compound-list
+.It
+compound command
+.It
+function definition
+.El
+.Pp
+Unless otherwise stated, the exit status of a command is that of the last
+simple command executed by the command.
+.Ss Pipelines
+A pipeline is a sequence of one or more commands separated
+by the control operator |.
+The standard output of all but
+the last command is connected to the standard input
+of the next command.
+The standard output of the last
+command is inherited from the shell, as usual.
+.Pp
+The format for a pipeline is:
+.Pp
+.Dl [!] command1 [ | command2 ...]
+.Pp
+The standard output of command1 is connected to the standard input of
+command2.
+The standard input, standard output, or both of a command is
+considered to be assigned by the pipeline before any redirection specified
+by redirection operators that are part of the command.
+.Pp
+If the pipeline is not in the background (discussed later), the shell
+waits for all commands to complete.
+.Pp
+If the reserved word ! does not precede the pipeline, the exit status is
+the exit status of the last command specified in the pipeline.
+Otherwise, the exit status is the logical NOT of the exit status of the
+last command.
+That is, if the last command returns zero, the exit status
+is 1; if the last command returns greater than zero, the exit status is
+zero.
+.Pp
+Because pipeline assignment of standard input or standard output or both
+takes place before redirection, it can be modified by redirection.
+For example:
+.Pp
+.Dl $ command1 2\*[Gt]&1 | command2
+.Pp
+sends both the standard output and standard error of command1
+to the standard input of command2.
+.Pp
+A ; or
+.Aq newline
+terminator causes the preceding AND-OR-list (described
+next) to be executed sequentially; a & causes asynchronous execution of
+the preceding AND-OR-list.
+.Pp
+Note that unlike some other shells, each process in the pipeline is a
+child of the invoking shell (unless it is a shell builtin, in which case
+it executes in the current shell -- but any effect it has on the
+environment is wiped).
+.Ss Background Commands -- &
+If a command is terminated by the control operator ampersand (&), the
+shell executes the command asynchronously -- that is, the shell does not
+wait for the command to finish before executing the next command.
+.Pp
+The format for running a command in background is:
+.Pp
+.Dl command1 & [command2 & ...]
+.Pp
+If the shell is not interactive, the standard input of an asynchronous
+command is set to
+.Pa /dev/null .
+.Ss Lists -- Generally Speaking
+A list is a sequence of zero or more commands separated by newlines,
+semicolons, or ampersands, and optionally terminated by one of these three
+characters.
+The commands in a list are executed in the order they are written.
+If command is followed by an ampersand, the shell starts the
+command and immediately proceeds onto the next command; otherwise it waits
+for the command to terminate before proceeding to the next one.
+.Ss Short-Circuit List Operators
+.Dq &&
+and
+.Dq ||
+are AND-OR list operators.
+.Dq &&
+executes the first command, and then executes the second command if and only
+if the exit status of the first command is zero.
+.Dq ||
+is similar, but executes the second command if and only if the exit status
+of the first command is nonzero.
+.Dq &&
+and
+.Dq ||
+both have the same priority.
+.Ss Flow-Control Constructs -- if, while, for, case
+The syntax of the if command is
+.Bd -literal -offset indent
+if list
+then list
+[ elif list
+then    list ] ...
+[ else list ]
+fi
+.Ed
+.Pp
+The syntax of the while command is
+.Bd -literal -offset indent
+while list
+do   list
+done
+.Ed
+.Pp
+The two lists are executed repeatedly while the exit status of the
+first list is zero.
+The until command is similar, but has the word
+until in place of while, which causes it to
+repeat until the exit status of the first list is zero.
+.Pp
+The syntax of the for command is
+.Bd -literal -offset indent
+for variable [ in [ word ... ] ]
+do   list
+done
+.Ed
+.Pp
+The words following
+.Pa in
+are expanded, and then the list is executed repeatedly with the
+variable set to each word in turn.
+Omitting in word ... is equivalent to in "$@".
+.Pp
+The syntax of the break and continue command is
+.Bd -literal -offset indent
+break [ num ]
+continue [ num ]
+.Ed
+.Pp
+Break terminates the num innermost for or while loops.
+Continue continues with the next iteration of the innermost loop.
+These are implemented as builtin commands.
+.Pp
+The syntax of the case command is
+.Bd -literal -offset indent
+case word in
+[(]pattern) list ;;
+\&...
+esac
+.Ed
+.Pp
+The pattern can actually be one or more patterns (see
+.Sx Shell Patterns
+described later), separated by
+.Dq \*(Ba
+characters.
+The
+.Do
+(
+.Dc
+character before the pattern is optional.
+.Ss Grouping Commands Together
+Commands may be grouped by writing either
+.Pp
+.Dl (list)
+.Pp
+or
+.Pp
+.Dl { list; }
+.Pp
+The first of these executes the commands in a subshell.
+Builtin commands grouped into a (list) will not affect the current shell.
+The second form does not fork another shell so is slightly more efficient.
+Grouping commands together this way allows you to redirect
+their output as though they were one program:
+.Pp
+.Bd -literal -offset indent
+{ printf \*q hello \*q ; printf \*q world\\n" ; } \*[Gt] greeting
+.Ed
+.Pp
+Note that
+.Dq }
+must follow a control operator (here,
+.Dq \&; )
+so that it is recognized as a reserved word and not as another command argument.
+.Ss Functions
+The syntax of a function definition is
+.Pp
+.Dl name ( ) command
+.Pp
+A function definition is an executable statement; when executed it
+installs a function named name and returns an exit status of zero.
+The command is normally a list enclosed between
+.Dq {
+and
+.Dq } .
+.Pp
+Variables may be declared to be local to a function by using a local
+command.
+This should appear as the first statement of a function, and the syntax is
+.Pp
+.Dl local [ variable | - ] ...
+.Pp
+Local is implemented as a builtin command.
+.Pp
+When a variable is made local, it inherits the initial value and exported
+and readonly flags from the variable with the same name in the surrounding
+scope, if there is one.
+Otherwise, the variable is initially unset.
+The shell uses dynamic scoping, so that if you make the variable x local to
+function f, which then calls function g, references to the variable x made
+inside g will refer to the variable x declared inside f, not to the global
+variable named x.
+.Pp
+The only special parameter that can be made local is
+.Dq - .
+Making
+.Dq -
+local any shell options that are changed via the set command inside the
+function to be restored to their original values when the function
+returns.
+.Pp
+The syntax of the return command is
+.Pp
+.Dl return [ exitstatus ]
+.Pp
+It terminates the currently executing function.
+Return is implemented as a builtin command.
+.Ss Variables and Parameters
+The shell maintains a set of parameters.
+A parameter denoted by a name is called a variable.
+When starting up, the shell turns all the environment
+variables into shell variables.
+New variables can be set using the form
+.Pp
+.Dl name=value
+.Pp
+Variables set by the user must have a name consisting solely of
+alphabetics, numerics, and underscores - the first of which must not be
+numeric.
+A parameter can also be denoted by a number or a special
+character as explained below.
+.Ss Positional Parameters
+A positional parameter is a parameter denoted by a number (n \*[Gt] 0).
+The shell sets these initially to the values of its command line arguments
+that follow the name of the shell script.
+The
+.Ic set
+builtin can also be used to set or reset them.
+.Ss Special Parameters
+A special parameter is a parameter denoted by one of the following special
+characters.
+The value of the parameter is listed next to its character.
+.Bl -tag -width thinhyphena
+.It *
+Expands to the positional parameters, starting from one.
+When the
+expansion occurs within a double-quoted string it expands to a single
+field with the value of each parameter separated by the first character of
+the
+.Ev IFS
+variable, or by a
+.Aq space
+if
+.Ev IFS
+is unset.
+.It @
+Expands to the positional parameters, starting from one.
+When the expansion occurs within double-quotes, each positional
+parameter expands as a separate argument.
+If there are no positional parameters, the
+expansion of @ generates zero arguments, even when @ is
+double-quoted.
+What this basically means, for example, is
+if $1 is
+.Dq abc
+and $2 is
+.Dq def ghi ,
+then
+.Qq $@
+expands to
+the two arguments:
+.Pp
+.Sm off
+.Dl \*q abc \*q \  \*q def\ ghi \*q
+.Sm on
+.It #
+Expands to the number of positional parameters.
+.It ?
+Expands to the exit status of the most recent pipeline.
+.It - (Hyphen.)
+Expands to the current option flags (the single-letter
+option names concatenated into a string) as specified on
+invocation, by the set builtin command, or implicitly
+by the shell.
+.It $
+Expands to the process ID of the invoked shell.
+A subshell retains the same value of $ as its parent.
+.It !
+Expands to the process ID of the most recent background
+command executed from the current shell.
+For a pipeline, the process ID is that of the last command in the pipeline.
+.It 0 (Zero.)
+Expands to the name of the shell or shell script.
+.El
+.Ss Word Expansions
+This clause describes the various expansions that are performed on words.
+Not all expansions are performed on every word, as explained later.
+.Pp
+Tilde expansions, parameter expansions, command substitutions, arithmetic
+expansions, and quote removals that occur within a single word expand to a
+single field.
+It is only field splitting or pathname expansion that can
+create multiple fields from a single word.
+The single exception to this
+rule is the expansion of the special parameter @ within double-quotes, as
+was described above.
+.Pp
+The order of word expansion is:
+.Bl -enum
+.It
+Tilde Expansion, Parameter Expansion, Command Substitution,
+Arithmetic Expansion (these all occur at the same time).
+.It
+Field Splitting is performed on fields
+generated by step (1) unless the
+.Ev IFS
+variable is null.
+.It
+Pathname Expansion (unless set
+.Fl f
+is in effect).
+.It
+Quote Removal.
+.El
+.Pp
+The $ character is used to introduce parameter expansion, command
+substitution, or arithmetic evaluation.
+.Ss Tilde Expansion (substituting a user's home directory)
+A word beginning with an unquoted tilde character (~) is
+subjected to tilde expansion.
+All the characters up to
+a slash (/) or the end of the word are treated as a username
+and are replaced with the user's home directory.
+If the username is missing (as in
+.Pa ~/foobar ) ,
+the tilde is replaced with the value of the
+.Va HOME
+variable (the current user's home directory).
+.Ss Parameter Expansion
+The format for parameter expansion is as follows:
+.Pp
+.Dl ${expression}
+.Pp
+where expression consists of all characters until the matching
+.Dq } .
+Any
+.Dq }
+escaped by a backslash or within a quoted string, and characters in
+embedded arithmetic expansions, command substitutions, and variable
+expansions, are not examined in determining the matching
+.Dq } .
+.Pp
+The simplest form for parameter expansion is:
+.Pp
+.Dl ${parameter}
+.Pp
+The value, if any, of parameter is substituted.
+.Pp
+The parameter name or symbol can be enclosed in braces, which are
+optional except for positional parameters with more than one digit or
+when parameter is followed by a character that could be interpreted as
+part of the name.
+If a parameter expansion occurs inside double-quotes:
+.Bl -enum
+.It
+Pathname expansion is not performed on the results of the expansion.
+.It
+Field splitting is not performed on the results of the
+expansion, with the exception of @.
+.El
+.Pp
+In addition, a parameter expansion can be modified by using one of the
+following formats.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${parameter:-word}
+Use Default Values.
+If parameter is unset or null, the expansion of word
+is substituted; otherwise, the value of parameter is substituted.
+.It ${parameter:=word}
+Assign Default Values.
+If parameter is unset or null, the expansion of
+word is assigned to parameter.
+In all cases, the final value of parameter is substituted.
+Only variables, not positional parameters or special
+parameters, can be assigned in this way.
+.It ${parameter:?[word]}
+Indicate Error if Null or Unset.
+If parameter is unset or null, the
+expansion of word (or a message indicating it is unset if word is omitted)
+is written to standard error and the shell exits with a nonzero exit status.
+Otherwise, the value of parameter is substituted.
+An interactive shell need not exit.
+.It ${parameter:+word}
+Use Alternative Value.
+If parameter is unset or null, null is
+substituted; otherwise, the expansion of word is substituted.
+.El
+.Pp
+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.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${#parameter}
+String Length.
+The length in characters of the value of parameter.
+.El
+.Pp
+The following four varieties of parameter expansion provide for substring
+processing.
+In each case, pattern matching notation (see
+.Sx Shell Patterns ) ,
+rather than regular expression notation, is used to evaluate the patterns.
+If parameter is * or @, the result of the expansion is unspecified.
+Enclosing the full parameter expansion string in double-quotes does not
+cause the following four varieties of pattern characters to be quoted,
+whereas quoting characters within the braces has this effect.
+.Bl -tag -width aaparameterwordaaaaa
+.It ${parameter%word}
+Remove Smallest Suffix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the
+smallest portion of the suffix matched by the pattern deleted.
+.It ${parameter%%word}
+Remove Largest Suffix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the largest
+portion of the suffix matched by the pattern deleted.
+.It ${parameter#word}
+Remove Smallest Prefix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the
+smallest portion of the prefix matched by the pattern deleted.
+.It ${parameter##word}
+Remove Largest Prefix Pattern.
+The word is expanded to produce a pattern.
+The parameter expansion then results in parameter, with the largest
+portion of the prefix matched by the pattern deleted.
+.El
+.Ss Command Substitution
+Command substitution allows the output of a command to be substituted in
+place of the command name itself.
+Command substitution occurs when the command is enclosed as follows:
+.Pp
+.Dl $(command)
+.Pp
+or
+.Po
+.Dq backquoted
+version
+.Pc :
+.Pp
+.Dl `command`
+.Pp
+The shell expands the command substitution by executing command in a
+subshell environment and replacing the command substitution with the
+standard output of the command, removing sequences of one or more
+.Ao newline Ac Ns s
+at the end of the substitution.
+(Embedded
+.Ao newline Ac Ns s
+before
+the end of the output are not removed; however, during field splitting,
+they may be translated into
+.Ao space Ac Ns s ,
+depending on the value of
+.Ev IFS
+and quoting that is in effect.)
+.Ss Arithmetic Expansion
+Arithmetic expansion provides a mechanism for evaluating an arithmetic
+expression and substituting its value.
+The format for arithmetic expansion is as follows:
+.Pp
+.Dl $((expression))
+.Pp
+The expression is treated as if it were in double-quotes, except
+that a double-quote inside the expression is not treated specially.
+The shell expands all tokens in the expression for parameter expansion,
+command substitution, and quote removal.
+.Pp
+Next, the shell treats this as an arithmetic expression and
+substitutes the value of the expression.
+.Ss White Space Splitting (Field Splitting)
+After parameter expansion, command substitution, and
+arithmetic expansion the shell scans the results of
+expansions and substitutions that did not occur in double-quotes for
+field splitting and multiple fields can result.
+.Pp
+The shell treats each character of the
+.Ev IFS
+as a delimiter and uses the delimiters to split the results of parameter
+expansion and command substitution into fields.
+.Ss Pathname Expansion (File Name Generation)
+Unless the
+.Fl f
+flag is set, file name generation is performed after word splitting is
+complete.
+Each word is viewed as a series of patterns, separated by slashes.
+The process of expansion replaces the word with the names of all
+existing files whose names can be formed by replacing each pattern with a
+string that matches the specified pattern.
+There are two restrictions on
+this: first, a pattern cannot match a string containing a slash, and
+second, a pattern cannot match a string starting with a period unless the
+first character of the pattern is a period.
+The next section describes the
+patterns used for both Pathname Expansion and the
+.Ic case
+command.
+.Ss Shell Patterns
+A pattern consists of normal characters, which match themselves,
+and meta-characters.
+The meta-characters are
+.Dq \&! ,
+.Dq * ,
+.Dq \&? ,
+and
+.Dq \&[ .
+These characters lose their special meanings if they are quoted.
+When command or variable substitution is performed
+and the dollar sign or back quotes are not double quoted,
+the value of the variable or the output of
+the command is scanned for these characters and they are turned into
+meta-characters.
+.Pp
+An asterisk
+.Pq Dq *
+matches any string of characters.
+A question mark matches any single character.
+A left bracket
+.Pq Dq \&[
+introduces a character class.
+The end of the character class is indicated by a
+.Pq Dq \&] ;
+if the
+.Dq \&]
+is missing then the
+.Dq \&[
+matches a
+.Dq \&[
+rather than introducing a character class.
+A character class matches any of the characters between the square brackets.
+A range of characters may be specified using a minus sign.
+The character class may be complemented
+by making an exclamation point the first character of the character class.
+.Pp
+To include a
+.Dq \&]
+in a character class, make it the first character listed (after the
+.Dq \&! ,
+if any).
+To include a minus sign, make it the first or last character listed.
+.Ss Builtins
+This section lists the builtin commands which are builtin because they
+need to perform some operation that can't be performed by a separate
+process.
+In addition to these, there are several other commands that may
+be builtin for efficiency (e.g.
+.Xr printf 1 ,
+.Xr echo 1 ,
+.Xr test 1 ,
+etc).
+.Bl -tag -width 5n
+.It :
+.It true
+A null command that returns a 0 (true) exit value.
+.It \&. file
+The commands in the specified file are read and executed by the shell.
+.It alias Op Ar name Ns Op Ar "=string ..."
+If
+.Ar name=string
+is specified, the shell defines the alias
+.Ar name
+with value
+.Ar string .
+If just
+.Ar name
+is specified, the value of the alias
+.Ar name
+is printed.
+With no arguments, the
+.Ic alias
+builtin prints the
+names and values of all defined aliases (see
+.Ic unalias ) .
+.It bg [ Ar job ] ...
+Continue the specified jobs (or the current job if no
+jobs are given) in the background.
+.It Xo command
+.Op Fl p
+.Op Fl v
+.Op Fl V
+.Ar command
+.Op Ar arg ...
+.Xc
+Execute the specified command but ignore shell functions when searching
+for it.
+(This is useful when you
+have a shell function with the same name as a builtin command.)
+.Bl -tag -width 5n
+.It Fl p
+search for command using a
+.Ev PATH
+that guarantees to find all the standard utilities.
+.It Fl V
+Do not execute the command but
+search for the command and print the resolution of the
+command search.
+This is the same as the type builtin.
+.It Fl v
+Do not execute the command but
+search for the command and print the absolute pathname
+of utilities, the name for builtins or the expansion of aliases.
+.El
+.It cd Ar -
+.It Xo cd Op Fl LP
+.Op Ar directory
+.Xc
+Switch to the specified directory (default
+.Ev HOME ) .
+If an entry for
+.Ev CDPATH
+appears in the environment of the
+.Ic cd
+command or the shell variable
+.Ev CDPATH
+is set and the directory name does not begin with a slash, then the
+directories listed in
+.Ev CDPATH
+will be searched for the specified directory.
+The format of
+.Ev CDPATH
+is the same as that of
+.Ev PATH .
+If a single dash is specified as the argument, it will be replaced by the
+value of
+.Ev OLDPWD .
+The
+.Ic cd
+command will print out the name of the
+directory that it actually switched to if this is different from the name
+that the user gave.
+These may be different either because the
+.Ev CDPATH
+mechanism was used or because the argument is a single dash.
+The
+.Fl P
+option causes the physical directory structure to be used, that is, all
+symbolic links are resolved to their respective values.  The
+.Fl L
+option turns off the effect of any preceding
+.Fl P
+options.
+.It Xo echo Op Fl n
+.Ar args... 
+.Xc
+Print the arguments on the standard output, separated by spaces.
+Unless the
+.Fl n
+option is present, a newline is output following the arguments.
+.Pp
+If any of the following sequences of characters is encountered during
+output, the sequence is not output.  Instead, the specified action is
+performed:
+.Bl -tag -width indent
+.It Li \eb
+A backspace character is output.
+.It Li \ec
+Subsequent output is suppressed.  This is normally used at the end of the
+last argument to suppress the trailing newline that
+.Ic echo
+would otherwise output.
+.It Li \ef
+Output a form feed.
+.It Li \en
+Output a newline character.
+.It Li \er
+Output a carriage return.
+.It Li \et
+Output a (horizontal) tab character.
+.It Li \ev
+Output a vertical tab.
+.It Li \e0 Ns Ar digits
+Output the character whose value is given by zero to three octal digits.
+If there are zero digits, a nul character is output.
+.It Li \e\e
+Output a backslash.
+.El
+.Pp
+All other backslash sequences elicit undefined behaviour.
+.It eval Ar string ...
+Concatenate all the arguments with spaces.
+Then re-parse and execute the command.
+.It exec Op Ar command arg ...
+Unless command is omitted, the shell process is replaced with the
+specified program (which must be a real program, not a shell builtin or
+function).
+Any redirections on the
+.Ic exec
+command are marked as permanent, so that they are not undone when the
+.Ic exec
+command finishes.
+.It exit Op Ar exitstatus
+Terminate the shell process.
+If
+.Ar exitstatus
+is given it is used as the exit status of the shell; otherwise the
+exit status of the preceding command is used.
+.It export Ar name ...
+.It export Fl p
+The specified names are exported so that they will appear in the
+environment of subsequent commands.
+The only way to un-export a variable is to unset it.
+The shell allows the value of a variable to be set at the
+same time it is exported by writing
+.Pp
+.Dl export name=value
+.Pp
+With no arguments the export command lists the names of all exported variables.
+With the
+.Fl p
+option specified the output will be formatted suitably for non-interactive use.
+.It Xo fc Op Fl e Ar editor
+.Op Ar first Op Ar last
+.Xc
+.It Xo fc Fl l
+.Op Fl nr
+.Op Ar first Op Ar last
+.Xc
+.It Xo fc Fl s Op Ar old=new
+.Op Ar first
+.Xc
+The
+.Ic fc
+builtin lists, or edits and re-executes, commands previously entered
+to an interactive shell.
+.Bl -tag -width 5n
+.It Fl e No editor
+Use the editor named by editor to edit the commands.
+The editor string is a command name, subject to search via the
+.Ev PATH
+variable.
+The value in the
+.Ev FCEDIT
+variable is used as a default when
+.Fl e
+is not specified.
+If
+.Ev FCEDIT
+is null or unset, the value of the
+.Ev EDITOR
+variable is used.
+If
+.Ev EDITOR
+is null or unset,
+.Xr ed 1
+is used as the editor.
+.It Fl l No (ell)
+List the commands rather than invoking an editor on them.
+The commands are written in the sequence indicated by
+the first and last operands, as affected by
+.Fl r ,
+with each command preceded by the command number.
+.It Fl n
+Suppress command numbers when listing with -l.
+.It Fl r
+Reverse the order of the commands listed (with
+.Fl l )
+or edited (with neither
+.Fl l
+nor
+.Fl s ) .
+.It Fl s
+Re-execute the command without invoking an editor.
+.It first
+.It last
+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
+variable.
+The value of first or last or both are one of the following:
+.Bl -tag -width 5n
+.It [+]number
+A positive number representing a command number; command numbers can be
+displayed with the
+.Fl l
+option.
+.It Fl number
+A negative decimal number representing the command that was executed
+number of commands previously.
+For example, \-1 is the immediately previous command.
+.El
+.It string
+A string indicating the most recently entered command that begins with
+that string.
+If the old=new operand is not also specified with
+.Fl s ,
+the string form of the first operand cannot contain an embedded equal sign.
+.El
+.Pp
+The following environment variables affect the execution of fc:
+.Bl -tag -width HISTSIZE
+.It Ev FCEDIT
+Name of the editor to use.
+.It Ev HISTSIZE
+The number of previous commands that are accessible.
+.El
+.It fg Op Ar job
+Move the specified job or the current job to the foreground.
+.It getopts Ar optstring var
+The
+.Tn POSIX
+.Ic getopts
+command, not to be confused with the
+.Em Bell Labs
+-derived
+.Xr getopt 1 .
+.Pp
+The first argument should be a series of letters, each of which may be
+optionally followed by a colon to indicate that the option requires an
+argument.
+The variable specified is set to the parsed option.
+.Pp
+The
+.Ic getopts
+command deprecates the older
+.Xr getopt 1
+utility due to its handling of arguments containing whitespace.
+.Pp
+The
+.Ic getopts
+builtin may be used to obtain options and their arguments
+from a list of parameters.
+When invoked,
+.Ic getopts
+places the value of the next option from the option string in the list in
+the shell variable specified by
+.Va var
+and its index in the shell variable
+.Ev OPTIND .
+When the shell is invoked,
+.Ev OPTIND
+is initialized to 1.
+For each option that requires an argument, the
+.Ic getopts
+builtin will place it in the shell variable
+.Ev OPTARG .
+If an option is not allowed for in the
+.Va optstring ,
+then
+.Ev OPTARG
+will be unset.
+.Pp
+.Va optstring
+is a string of recognized option letters (see
+.Xr getopt 3 ) .
+If a letter is followed by a colon, the option is expected to have an
+argument which may or may not be separated from it by white space.
+If an option character is not found where expected,
+.Ic getopts
+will set the variable
+.Va var
+to a
+.Dq \&? ;
+.Ic getopts
+will then unset
+.Ev OPTARG
+and write output to standard error.
+By specifying a colon as the first character of
+.Va optstring
+all errors will be ignored.
+.Pp
+After the last option
+.Ic getopts
+will return a non-zero value and set
+.Va var
+to
+.Dq \&? .
+.Pp
+The following code fragment shows how one might process the arguments
+for a command that can take the options
+.Op a
+and
+.Op b ,
+and the option
+.Op c ,
+which requires an argument.
+.Pp
+.Bd -literal -offset indent
+while getopts abc: f
+do
+	case $f in
+	a | b)	flag=$f;;
+	c)	carg=$OPTARG;;
+	\\?)	echo $USAGE; exit 1;;
+	esac
+done
+shift `expr $OPTIND - 1`
+.Ed
+.Pp
+This code will accept any of the following as equivalent:
+.Pp
+.Bd -literal -offset indent
+cmd \-acarg file file
+cmd \-a \-c arg file file
+cmd \-carg -a file file
+cmd \-a \-carg \-\- file file
+.Ed
+.It hash Fl rv Ar command ...
+The shell maintains a hash table which remembers the
+locations of commands.
+With no arguments whatsoever,
+the
+.Ic hash
+command prints out the contents of this table.
+Entries which have not been looked at since the last
+.Ic cd
+command are marked with an asterisk; it is possible for these entries
+to be invalid.
+.Pp
+With arguments, the
+.Ic hash
+command removes the specified commands from the hash table (unless
+they are functions) and then locates them.
+With the
+.Fl v
+option, hash prints the locations of the commands as it finds them.
+The
+.Fl r
+option causes the hash command to delete all the entries in the hash table
+except for functions.
+.It pwd Op Fl LP
+builtin command remembers what the current directory
+is rather than recomputing it each time.
+This makes it faster.
+However, if the current directory is renamed, the builtin version of
+.Ic pwd
+will continue to print the old name for the directory.
+The
+.Fl P
+option causes the physical value of the current working directory to be shown,
+that is, all symbolic links are resolved to their respective values.  The
+.Fl L
+option turns off the effect of any preceding
+.Fl P
+options.
+.It Xo read Op Fl p Ar prompt
+.Op Fl r
+.Ar variable
+.Op Ar ...
+.Xc
+The prompt is printed if the
+.Fl p
+option is specified and the standard input is a terminal.
+Then a line is read from the standard input.
+The trailing newline is deleted from the
+line and the line is split as described in the section on word splitting
+above, and the pieces are assigned to the variables in order.
+At least one variable must be specified.
+If there are more pieces than variables, the remaining pieces
+(along with the characters in
+.Ev IFS
+that separated them) are assigned to the last variable.
+If there are more variables than pieces,
+the remaining variables are assigned the null string.
+The
+.Ic read
+builtin will indicate success unless EOF is encountered on input, in
+which case failure is returned.
+.Pp
+By default, unless the
+.Fl r
+option is specified, the backslash
+.Dq \e
+acts as an escape character, causing the following character to be treated
+literally.
+If a backslash is followed by a newline, the backslash and the
+newline will be deleted.
+.It readonly Ar name ...
+.It readonly Fl p
+The specified names are marked as read only, so that they cannot be
+subsequently modified or unset.
+The shell allows the value of a variable
+to be set at the same time it is marked read only by writing
+.Pp
+.Dl readonly name=value
+.Pp
+With no arguments the readonly command lists the names of all read only
+variables.
+With the
+.Fl p
+option specified the output will be formatted suitably for non-interactive use.
+.Pp
+.It Xo printf Ar format
+.Op Ar arguments  ...
+.Xc
+.Ic printf
+formats and prints its arguments, after the first, under control
+of the
+.Ar format  .
+The
+.Ar format
+is a character string which contains three types of objects: plain characters,
+which are simply copied to standard output, character escape sequences which
+are converted and copied to the standard output, and format specifications,
+each of which causes printing of the next successive
+.Ar argument  .
+.Pp
+The
+.Ar arguments
+after the first are treated as strings if the corresponding format is
+either
+.Cm b ,
+.Cm c
+or
+.Cm s ;
+otherwise it is evaluated as a C constant, with the following extensions:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+A leading plus or minus sign is allowed.
+.It
+If the leading character is a single or double quote, the value is the
+.Tn ASCII
+code of the next character.
+.El
+.Pp
+The format string is reused as often as necessary to satisfy the
+.Ar arguments  .
+Any extra format specifications are evaluated with zero or the null
+string.
+.Pp
+Character escape sequences are in backslash notation as defined in
+.St -ansiC .
+The characters and their meanings are as follows:
+.Bl -tag -width Ds -offset indent
+.It Cm \ea
+Write a \*[Lt]bell\*[Gt] character.
+.It Cm \eb
+Write a \*[Lt]backspace\*[Gt] character.
+.It Cm \ef
+Write a \*[Lt]form-feed\*[Gt] character.
+.It Cm \en
+Write a \*[Lt]new-line\*[Gt] character.
+.It Cm \er
+Write a \*[Lt]carriage return\*[Gt] character.
+.It Cm \et
+Write a \*[Lt]tab\*[Gt] character.
+.It Cm \ev
+Write a \*[Lt]vertical tab\*[Gt] character.
+.It Cm \e\e
+Write a backslash character.
+.It Cm \e Ns Ar num
+Write an 8\-bit character whose
+.Tn ASCII
+value is the 1\-, 2\-, or 3\-digit
+octal number
+.Ar num .
+.El
+.Pp
+Each format specification is introduced by the percent character
+(``%'').
+The remainder of the format specification includes,
+in the following order:
+.Bl -tag -width Ds
+.It "Zero or more of the following flags:"
+.Bl -tag -width Ds
+.It Cm #
+A `#' character
+specifying that the value should be printed in an ``alternative form''.
+For
+.Cm b ,
+.Cm c ,
+.Cm d ,
+and
+.Cm s
+formats, this option has no effect.
+For the
+.Cm o
+format the precision of the number is increased to force the first
+character of the output string to a zero.
+For the
+.Cm x
+.Pq Cm X
+format, a non-zero result has the string
+.Li 0x
+.Pq Li 0X
+prepended to it.
+For
+.Cm e  ,
+.Cm E ,
+.Cm f  ,
+.Cm g ,
+and
+.Cm G
+formats, the result will always contain a decimal point, even if no
+digits follow the point (normally, a decimal point only appears in the
+results of those formats if a digit follows the decimal point).
+For
+.Cm g
+and
+.Cm G
+formats, trailing zeros are not removed from the result as they
+would otherwise be.
+.It Cm \&\-
+A minus sign `\-' which specifies
+.Em left adjustment
+of the output in the indicated field;
+.It Cm \&+
+A `+' character specifying that there should always be
+a sign placed before the number when using signed formats.
+.It Sq \&\ \&
+A space specifying that a blank should be left before a positive number
+for a signed format.
+A `+' overrides a space if both are used;
+.It Cm \&0
+A zero `0' character indicating that zero-padding should be used
+rather than blank-padding.
+A `\-' overrides a `0' if both are used;
+.El
+.It "Field Width:"
+An optional digit string specifying a
+.Em field width ;
+if the output string has fewer characters than the field width it will
+be blank-padded on the left (or right, if the left-adjustment indicator
+has been given) to make up the field width (note that a leading zero
+is a flag, but an embedded zero is part of a field width);
+.It Precision :
+An optional period,
+.Sq Cm \&.\& ,
+followed by an optional digit string giving a
+.Em precision
+which specifies the number of digits to appear after the decimal point,
+for
+.Cm e
+and
+.Cm f
+formats, or the maximum number of bytes to be printed
+from a string
+.Sm off
+.Pf ( Cm b
+.Sm on
+and
+.Cm s
+formats); if the digit string is missing, the precision is treated
+as zero;
+.It Format :
+A character which indicates the type of format to use (one of
+.Cm diouxXfwEgGbcs ) .
+.El
+.Pp
+A field width or precision may be
+.Sq Cm \&*
+instead of a digit string.
+In this case an
+.Ar argument
+supplies the field width or precision.
+.Pp
+The format characters and their meanings are:
+.Bl -tag -width Fl
+.It Cm diouXx
+The
+.Ar argument
+is printed as a signed decimal (d or i), unsigned octal, unsigned decimal,
+or unsigned hexadecimal (X or x), respectively.
+.It Cm f
+The
+.Ar argument
+is printed in the style
+.Sm off
+.Pf [\-]ddd Cm \&. No ddd
+.Sm on
+where the number of d's
+after the decimal point is equal to the precision specification for
+the argument.
+If the precision is missing, 6 digits are given; if the precision
+is explicitly 0, no digits and no decimal point are printed.
+.It Cm eE
+The
+.Ar argument
+is printed in the style
+.Sm off
+.Pf [\-]d Cm \&. No ddd Cm e No \*(Pmdd
+.Sm on
+where there
+is one digit before the decimal point and the number after is equal to
+the precision specification for the argument; when the precision is
+missing, 6 digits are produced.
+An upper-case E is used for an `E' format.
+.It Cm gG
+The
+.Ar argument
+is printed in style
+.Cm f
+or in style
+.Cm e
+.Pq Cm E
+whichever gives full precision in minimum space.
+.It Cm b
+Characters from the string
+.Ar argument
+are printed with backslash-escape sequences expanded.
+.br
+The following additional backslash-escape sequences are supported:
+.Bl -tag -width Ds
+.It Cm \ec
+Causes
+.Nm
+to ignore any remaining characters in the string operand containing it,
+any remaining string operands, and any additional characters in
+the format operand.
+.It Cm \e0 Ns Ar num
+Write an 8\-bit character whose
+.Tn ASCII
+value is the 1\-, 2\-, or 3\-digit
+octal number
+.Ar num .
+.El
+.It Cm c
+The first character of
+.Ar argument
+is printed.
+.It Cm s
+Characters from the string
+.Ar argument
+are printed until the end is reached or until the number of bytes
+indicated by the precision specification is reached; if the
+precision is omitted, all characters in the string are printed.
+.It Cm \&%
+Print a `%'; no argument is used.
+.El
+.Pp
+In no case does a non-existent or small field width cause truncation of
+a field; padding takes place only if the specified field width exceeds
+the actual width.
+.It Xo set
+.Oo {
+.Fl options | Cm +options | Cm -- }
+.Oc Ar arg ...
+.Xc
+The
+.Ic set
+command performs three different functions.
+.Pp
+With no arguments, it lists the values of all shell variables.
+.Pp
+If options are given, it sets the specified option
+flags, or clears them as described in the section called
+.Sx Argument List Processing .
+As a special case, if the option is -o or +o and no argument is
+supplied, the shell prints the settings of all its options.  If the
+option is -o, the settings are printed in a human-readable format; if
+the option is +o, the settings are printed in a format suitable for
+reinput to the shell to affect the same option settings.
+.Pp
+The third use of the set command is to set the values of the shell's
+positional parameters to the specified args.
+To change the positional
+parameters without changing any options, use
+.Dq --
+as the first argument to set.
+If no args are present, the set command
+will clear all the positional parameters (equivalent to executing
+.Dq shift $# . )
+.It shift Op Ar n
+Shift the positional parameters n times.
+A
+.Ic shift
+sets the value of
+.Va $1
+to the value of
+.Va $2 ,
+the value of
+.Va $2
+to the value of
+.Va $3 ,
+and so on, decreasing
+the value of
+.Va $#
+by one.
+If n is greater than the number of positional parameters,
+.Ic shift
+will issue an error message, and exit with return status 2.
+.It test Ar expression
+.It \&[ Ar expression Cm \&]
+The
+.Ic test
+utility evaluates the expression and, if it evaluates
+to true, returns a zero (true) exit status; otherwise
+it returns 1 (false).
+If there is no expression, test also
+returns 1 (false).
+.Pp
+All operators and flags are separate arguments to the
+.Ic test
+utility.
+.Pp
+The following primaries are used to construct expression:
+.Bl -tag -width Ar
+.It Fl b Ar file
+True if
+.Ar file
+exists and is a block special
+file.
+.It Fl c Ar file
+True if
+.Ar file
+exists and is a character
+special file.
+.It Fl d Ar file
+True if
+.Ar file
+exists and is a directory.
+.It Fl e Ar file
+True if
+.Ar file
+exists (regardless of type).
+.It Fl f Ar file
+True if
+.Ar file
+exists and is a regular file.
+.It Fl g Ar file
+True if
+.Ar file
+exists and its set group ID flag
+is set.
+.It Fl h Ar file
+True if
+.Ar file
+exists and is a symbolic link.
+.It Fl k Ar file
+True if
+.Ar file
+exists and its sticky bit is set.
+.It Fl n Ar string
+True if the length of
+.Ar string
+is nonzero.
+.It Fl p Ar file
+True if
+.Ar file
+is a named pipe
+.Po Tn FIFO Pc .
+.It Fl r Ar file
+True if
+.Ar file
+exists and is readable.
+.It Fl s Ar file
+True if
+.Ar file
+exists and has a size greater
+than zero.
+.It Fl t Ar file_descriptor
+True if the file whose file descriptor number
+is
+.Ar file_descriptor
+is open and is associated with a terminal.
+.It Fl u Ar file
+True if
+.Ar file
+exists and its set user ID flag
+is set.
+.It Fl w Ar file
+True if
+.Ar file
+exists and is writable.
+True
+indicates only that the write flag is on.
+The file is not writable on a read-only file
+system even if this test indicates true.
+.It Fl x Ar file
+True if
+.Ar file
+exists and is executable.
+True
+indicates only that the execute flag is on.
+If
+.Ar file
+is a directory, true indicates that
+.Ar file
+can be searched.
+.It Fl z Ar string
+True if the length of
+.Ar string
+is zero.
+.It Fl L Ar file
+True if
+.Ar file
+exists and is a symbolic link.
+This operator is retained for compatibility with previous versions of
+this program.
+Do not rely on its existence; use
+.Fl h
+instead.
+.It Fl O Ar file
+True if
+.Ar file
+exists and its owner matches the effective user id of this process.
+.It Fl G Ar file
+True if
+.Ar file
+exists and its group matches the effective group id of this process.
+.It Fl S Ar file
+True if
+.Ar file
+exists and is a socket.
+.It Ar file1 Fl nt Ar file2
+True if
+.Ar file1
+and
+.Ar file2
+exist and
+.Ar file1
+is newer than
+.Ar file2 .
+.It Ar file1 Fl ot Ar file2
+True if
+.Ar file1
+and
+.Ar file2
+exist and
+.Ar file1
+is older than
+.Ar file2 .
+.It Ar file1 Fl ef Ar file2
+True if
+.Ar file1
+and
+.Ar file2
+exist and refer to the same file.
+.It Ar string
+True if
+.Ar string
+is not the null
+string.
+.It Ar \&s\&1 Cm \&= Ar \&s\&2
+True if the strings
+.Ar \&s\&1
+and
+.Ar \&s\&2
+are identical.
+.It Ar \&s\&1 Cm \&!= Ar \&s\&2
+True if the strings
+.Ar \&s\&1
+and
+.Ar \&s\&2
+are not identical.
+.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2
+True if string
+.Ar \&s\&1
+comes before
+.Ar \&s\&2
+based on the ASCII value of their characters.
+.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2
+True if string
+.Ar \&s\&1
+comes after
+.Ar \&s\&2
+based on the ASCII value of their characters.
+.It Ar \&n\&1 Fl \&eq Ar \&n\&2
+True if the integers
+.Ar \&n\&1
+and
+.Ar \&n\&2
+are algebraically
+equal.
+.It Ar \&n\&1 Fl \&ne Ar \&n\&2
+True if the integers
+.Ar \&n\&1
+and
+.Ar \&n\&2
+are not
+algebraically equal.
+.It Ar \&n\&1 Fl \&gt Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically
+greater than the integer
+.Ar \&n\&2 .
+.It Ar \&n\&1 Fl \&ge Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically
+greater than or equal to the integer
+.Ar \&n\&2 .
+.It Ar \&n\&1 Fl \&lt Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically less
+than the integer
+.Ar \&n\&2 .
+.It Ar \&n\&1 Fl \&le Ar \&n\&2
+True if the integer
+.Ar \&n\&1
+is algebraically less
+than or equal to the integer
+.Ar \&n\&2 .
+.El
+.Pp
+These primaries can be combined with the following operators:
+.Bl -tag -width Ar
+.It Cm \&! Ar expression
+True if
+.Ar expression
+is false.
+.It Ar expression1 Fl a Ar expression2
+True if both
+.Ar expression1
+and
+.Ar expression2
+are true.
+.It Ar expression1 Fl o Ar expression2
+True if either
+.Ar expression1
+or
+.Ar expression2
+are true.
+.It Cm \&( Ns Ar expression Ns Cm \&)
+True if expression is true.
+.El
+.Pp
+The
+.Fl a
+operator has higher precedence than the
+.Fl o
+operator.
+.It times
+Print the accumulated user and system times for the shell and for processes
+run from the shell.  The return status is 0.
+.It Xo trap
+.Op Ar action Ar signal ...
+.Xc
+Cause the shell to parse and execute action when any of the specified
+signals are received.
+The signals are specified by signal number or as the name of the signal.
+If
+.Ar signal
+is
+.Li 0
+or
+.Li EXIT ,
+the action is executed when the shell exits.
+.Ar action
+may be empty
+.Li ( "''" ) ,
+which causes the specified signals to be ignored.
+With
+.Ar action
+omitted or set to `-' the specified signals are set to their default action.
+When the shell forks off a subshell, it resets trapped (but not ignored)
+signals to the default action.
+The
+.Ic trap
+command has no effect on signals that were
+ignored on entry to the shell.
+.Ic trap
+without any arguments cause it to write a list of signals and their
+associated action to the standard output in a format that is suitable
+as an input to the shell that achieves the same trapping results.
+.Pp
+Examples:
+.Pp
+.Dl trap
+.Pp
+List trapped signals and their corresponding action
+.Pp
+.Dl trap '' INT QUIT tstp 30
+.Pp
+Ignore signals INT QUIT TSTP USR1
+.Pp
+.Dl trap date INT
+.Pp
+Print date upon receiving signal INT
+.It type Op Ar name ...
+Interpret each name as a command and print the resolution of the command
+search.
+Possible resolutions are:
+shell keyword, alias, shell builtin,
+command, tracked alias and not found.
+For aliases the alias expansion is
+printed; for commands and tracked aliases the complete pathname of the
+command is printed.
+.It ulimit Xo
+.Op Fl H \*(Ba Fl S
+.Op Fl a \*(Ba Fl tfdscmlpnv Op Ar value
+.Xc
+Inquire about or set the hard or soft limits on processes or set new
+limits.
+The choice between hard limit (which no process is allowed to
+violate, and which may not be raised once it has been lowered) and soft
+limit (which causes processes to be signaled but not necessarily killed,
+and which may be raised) is made with these flags:
+.Bl -tag -width Fl
+.It Fl H
+set or inquire about hard limits
+.It Fl S
+set or inquire about soft limits.
+If neither
+.Fl H
+nor
+.Fl S
+is specified, the soft limit is displayed or both limits are set.
+If both are specified, the last one wins.
+.El
+.Pp
+The limit to be interrogated or set, then, is chosen by specifying
+any one of these flags:
+.Bl -tag -width Fl
+.It Fl a
+show all the current limits
+.It Fl t
+show or set the limit on CPU time (in seconds)
+.It Fl f
+show or set the limit on the largest file that can be created
+(in 512-byte blocks)
+.It Fl d
+show or set the limit on the data segment size of a process (in kilobytes)
+.It Fl s
+show or set the limit on the stack size of a process (in kilobytes)
+.It Fl c
+show or set the limit on the largest core dump size that can be produced
+(in 512-byte blocks)
+.It Fl m
+show or set the limit on the total physical memory that can be
+in use by a process (in kilobytes)
+.It Fl l
+show or set the limit on how much memory a process can lock with
+.Xr mlock 2
+(in kilobytes)
+.It Fl p
+show or set the limit on the number of processes this user can
+have at one time
+.It Fl n
+show or set the limit on the number files a process can have open at once
+.It Fl v
+show or set the limit on the total virtual memory that can be
+in use by a process (in kilobytes)
+.It Fl r
+show or set the limit on the real-time scheduling priority of a process
+.El
+.Pp
+If none of these is specified, it is the limit on file size that is shown
+or set.
+If value is specified, the limit is set to that number; otherwise
+the current limit is displayed.
+.Pp
+Limits of an arbitrary process can be displayed or set using the
+.Xr sysctl 8
+utility.
+.Pp
+.It umask Op Ar mask
+Set the value of umask (see
+.Xr umask 2 )
+to the specified octal value.
+If the argument is omitted, the umask value is printed.
+.It unalias Xo
+.Op Fl a
+.Op Ar name
+.Xc
+If
+.Ar name
+is specified, the shell removes that alias.
+If
+.Fl a
+is specified, all aliases are removed.
+.It unset Xo
+.Op Fl fv
+.Ar name ...
+.Xc
+The specified variables and functions are unset and unexported.
+If
+.Fl f
+or
+.Fl v
+is specified, the corresponding function or variable is unset, respectively.
+If a given name corresponds to both a variable and a function, and no
+options are given, only the variable is unset.
+.It wait Op Ar job
+Wait for the specified job to complete and return the exit status of the
+last process in the job.
+If the argument is omitted, wait for all jobs to
+complete and return an exit status of zero.
+.El
+.Ss Command Line Editing
+When
+.Nm
+is being used interactively from a terminal, the current command
+and the command history (see
+.Ic fc
+in
+.Sx Builtins )
+can be edited using vi-mode command-line editing.
+This mode uses commands, described below,
+similar to a subset of those described in the vi man page.
+The command
+.Ql set -o vi
+enables vi-mode editing and places sh into vi insert mode.
+With vi-mode
+enabled, sh can be switched between insert mode and command mode.
+It is similar to vi: typing
+.Aq ESC
+enters vi command mode.
+Hitting
+.Aq return
+while in command mode will pass the line to the shell.
+.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.
+If the shell is not an
+interactive shell, the execution of the shell file will be aborted.
+Otherwise
+the shell will return the exit status of the last command executed, or
+if the exit builtin is used with a numeric argument, it will return the
+argument.
+.Sh ENVIRONMENT
+.Bl -tag -width MAILCHECK
+.It Ev HOME
+Set automatically by
+.Xr login 1
+from the user's login directory in the password file
+.Pq Xr passwd 4 .
+This environment variable also functions as the default argument for the
+cd builtin.
+.It Ev PATH
+The default search path for executables.
+See the above section
+.Sx Path Search .
+.It Ev CDPATH
+The search path used with the cd builtin.
+.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 MAILCHECK
+The frequency in seconds that the shell checks for the arrival of mail
+in the files specified by the
+.Ev MAILPATH
+or the
+.Ev MAIL
+file.
+If set to 0, the check will occur at each prompt.
+.It Ev MAILPATH
+A colon
+.Dq \&:
+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 PS1
+The primary prompt string, which defaults to
+.Dq $\  ,
+unless you are the superuser, in which case it defaults to
+.Dq #\  .
+.It Ev PS2
+The secondary prompt string, which defaults to
+.Dq \*[Gt]\  .
+.It Ev PS4
+Output before each line when execution trace (set -x) is enabled,
+defaults to
+.Dq +\  .
+.It Ev RPS1
+The primary right prompt string.
+.It Ev RPS2
+The secondary right prompt string.
+.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 TERM
+The default terminal setting for the shell.
+This is inherited by
+children of the shell, and is used in the history editing modes.
+.It Ev HISTSIZE
+The number of lines in the history buffer for the shell.
+.It Ev PWD
+The logical value of the current working directory.  This is set by the
+.Ic cd
+command.
+.It Ev OLDPWD
+The previous logical value of the current working directory.  This is set by
+the
+.Ic cd
+command.
+.It Ev PPID
+The process ID of the parent process of the shell.
+.El
+.Sh FILES
+.Bl -item -width HOMEprofilexxxx
+.It
+.Pa $HOME/.profile
+.It
+.Pa /etc/profile
+.El
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr echo 1 ,
+.Xr getopt 1 ,
+.Xr ksh 1 ,
+.Xr login 1 ,
+.Xr printf 1 ,
+.Xr test 1 ,
+.Xr getopt 3 ,
+.Xr passwd 5 ,
+.\" .Xr profile 4 ,
+.Xr environ 7 ,
+.Xr sysctl 8
+.Sh HISTORY
+.Nm
+is a POSIX-compliant implementation of /bin/sh that aims to be as small as
+possible.
+.Nm
+is a direct descendant of the NetBSD version of ash (the Almquist SHell),
+ported to Linux in early 1997.
+It was renamed to
+.Nm
+in 2002.
+.Sh BUGS
+Setuid shell scripts should be avoided at all costs, as they are a
+significant security risk.
+.Pp
+PS1, PS2, and PS4 should be subject to parameter expansion before
+being displayed.
diff --git a/bin/dash/src/error.c b/bin/dash/src/error.c
new file mode 100644
index 00000000..728ff885
--- /dev/null
+++ b/bin/dash/src/error.c
@@ -0,0 +1,238 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Errors and exceptions.
+ */
+
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "jobs.h"
+#include "shell.h"
+#include "main.h"
+#include "options.h"
+#include "output.h"
+#include "error.h"
+#include "show.h"
+#include "eval.h"
+#include "parser.h"
+#include "system.h"
+
+
+/*
+ * Code to handle exceptions in C.
+ */
+
+struct jmploc *handler;
+int exception;
+int suppressint;
+volatile sig_atomic_t intpending;
+int errlinno;
+
+
+static void exverror(int, const char *, va_list)
+    __attribute__((__noreturn__));
+
+/*
+ * 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".
+ */
+
+void
+exraise(int e)
+{
+#ifdef DEBUG
+	if (handler == NULL)
+		abort();
+#endif
+
+	if (vforked)
+		_exit(exitstatus);
+
+	INTOFF;
+
+	exception = e;
+	longjmp(handler->loc, 1);
+}
+
+
+/*
+ * Called from trap.c when a SIGINT is received.  (If the user specifies
+ * that SIGINT is to be trapped or ignored using the trap builtin, then
+ * this routine is not called.)  Suppressint is nonzero when interrupts
+ * are held using the INTOFF macro.  (The test for iflag is just
+ * defensive programming.)
+ */
+
+void
+onint(void) {
+
+	intpending = 0;
+	sigclearmask();
+	if (!(rootshell && iflag)) {
+		signal(SIGINT, SIG_DFL);
+		raise(SIGINT);
+	}
+	exitstatus = SIGINT + 128;
+	exraise(EXINT);
+	/* NOTREACHED */
+}
+
+static void
+exvwarning2(const char *msg, va_list ap)
+{
+	struct output *errs;
+	const char *name;
+	const char *fmt;
+
+	errs = out2;
+	name = arg0 ? arg0 : "sh";
+	if (!commandname)
+		fmt = "%s: %d: ";
+	else
+		fmt = "%s: %d: %s: ";
+	outfmt(errs, fmt, name, errlinno, commandname);
+	doformat(errs, msg, ap);
+#if FLUSHERR
+	outc('\n', errs);
+#else
+	outcslow('\n', errs);
+#endif
+}
+
+#define exvwarning(a, b, c) exvwarning2(b, c)
+
+/*
+ * Exverror is called to raise the error exception.  If the second argument
+ * is not NULL then error prints an error message using printf style
+ * formatting.  It then raises the error exception.
+ */
+static void
+exverror(int cond, const char *msg, va_list ap)
+{
+#ifdef DEBUG
+	if (msg) {
+		va_list aq;
+		TRACE(("exverror(%d, \"", cond));
+		va_copy(aq, ap);
+		TRACEV((msg, aq));
+		va_end(aq);
+		TRACE(("\") pid=%d\n", getpid()));
+	} else
+		TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
+	if (msg)
+#endif
+		exvwarning(-1, msg, ap);
+
+	flushall();
+	exraise(cond);
+	/* NOTREACHED */
+}
+
+
+void
+sh_error(const char *msg, ...)
+{
+	va_list ap;
+
+	exitstatus = 2;
+
+	va_start(ap, msg);
+	exverror(EXERROR, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+
+void
+exerror(int cond, const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+	exverror(cond, msg, ap);
+	/* NOTREACHED */
+	va_end(ap);
+}
+
+/*
+ * error/warning routines for external builtins
+ */
+
+void
+sh_warnx(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	exvwarning(-1, fmt, ap);
+	va_end(ap);
+}
+
+
+/*
+ * Return a string describing an error.  The returned string may be a
+ * pointer to a static buffer that will be overwritten on the next call.
+ * Action describes the operation that got the error.
+ */
+
+const char *
+errmsg(int e, int action)
+{
+	if (e != ENOENT && e != ENOTDIR)
+		return strerror(e);
+
+	if (action & E_OPEN)
+		return "No such file";
+	else if (action & E_CREAT)
+		return "Directory nonexistent";
+	else
+		return "not found";
+}
+
+
+#ifdef REALLY_SMALL
+void
+__inton() {
+	if (--suppressint == 0 && intpending) {
+		onint();
+	}
+}
+#endif
diff --git a/bin/dash/src/error.h b/bin/dash/src/error.h
new file mode 100644
index 00000000..94e30a27
--- /dev/null
+++ b/bin/dash/src/error.h
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)error.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <setjmp.h>
+#include <signal.h>
+
+/*
+ * Types of operations (passed to the errmsg routine).
+ */
+
+#define E_OPEN 01	/* opening a file */
+#define E_CREAT 02	/* creating a file */
+#define E_EXEC 04	/* executing a program */
+
+
+/*
+ * We enclose jmp_buf in a structure so that we can declare pointers to
+ * jump locations.  The global variable handler contains the location to
+ * jump to when an exception occurs, and the global variable exception
+ * contains a code identifying the exeception.  To implement nested
+ * exception handlers, the user should save the value of handler on entry
+ * to an inner scope, set handler to point to a jmploc structure for the
+ * inner scope, and restore handler on exit from the scope.
+ */
+
+struct jmploc {
+	jmp_buf loc;
+};
+
+extern struct jmploc *handler;
+extern int exception;
+
+/* exceptions */
+#define EXINT 0		/* SIGINT received */
+#define EXERROR 1	/* a generic error */
+#define EXEND 3		/* exit the shell */
+#define EXEXIT 4	/* exit the shell via exitcmd */
+
+
+/*
+ * These macros allow the user to suspend the handling of interrupt signals
+ * over a period of time.  This is similar to SIGHOLD to or sigblock, but
+ * much more efficient and portable.  (But hacking the kernel is so much
+ * more fun than worrying about efficiency and portability. :-))
+ */
+
+extern int suppressint;
+extern volatile sig_atomic_t intpending;
+
+#define barrier() ({ __asm__ __volatile__ ("": : :"memory"); })
+#define INTOFF \
+	({ \
+		suppressint++; \
+		barrier(); \
+		0; \
+	})
+#ifdef REALLY_SMALL
+void __inton(void);
+#define INTON __inton()
+#else
+#define INTON \
+	({ \
+		barrier(); \
+		if (--suppressint == 0 && intpending) onint(); \
+		0; \
+	})
+#endif
+#define FORCEINTON \
+	({ \
+		barrier(); \
+		suppressint = 0; \
+		if (intpending) onint(); \
+		0; \
+	})
+#define SAVEINT(v) ((v) = suppressint)
+#define RESTOREINT(v) \
+	({ \
+		barrier(); \
+		if ((suppressint = (v)) == 0 && intpending) onint(); \
+		0; \
+	})
+#define CLEAR_PENDING_INT intpending = 0
+#define int_pending() intpending
+
+void exraise(int) __attribute__((__noreturn__));
+#ifdef USE_NORETURN
+void onint(void) __attribute__((__noreturn__));
+#else
+void onint(void);
+#endif
+extern int errlinno;
+void sh_error(const char *, ...) __attribute__((__noreturn__));
+void exerror(int, const char *, ...) __attribute__((__noreturn__));
+const char *errmsg(int, int);
+
+void sh_warnx(const char *, ...);
diff --git a/bin/dash/src/eval.c b/bin/dash/src/eval.c
new file mode 100644
index 00000000..1b5d61dc
--- /dev/null
+++ b/bin/dash/src/eval.c
@@ -0,0 +1,1147 @@
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+/*
+ * Evaluate a command.
+ */
+
+#include "init.h"
+#include "main.h"
+#include "shell.h"
+#include "nodes.h"
+#include "syntax.h"
+#include "expand.h"
+#include "parser.h"
+#include "jobs.h"
+#include "eval.h"
+#include "builtins.h"
+#include "options.h"
+#include "exec.h"
+#include "redir.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "show.h"
+#include "mystring.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+
+
+int evalskip;			/* set if we are skipping commands */
+STATIC int skipcount;		/* number of levels to skip */
+MKINIT int loopnest;		/* current loop nesting level */
+static int funcline;		/* starting line number of current function, or 0 if not in a function */
+
+
+char *commandname;
+int exitstatus;			/* exit status of last command */
+int back_exitstatus;		/* exit status of backquoted command */
+int savestatus = -1;		/* exit status of last command outside traps */
+
+
+#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
+STATIC
+#endif
+void evaltreenr(union node *, int) __attribute__ ((__noreturn__));
+STATIC int evalloop(union node *, int);
+STATIC int evalfor(union node *, int);
+STATIC int evalcase(union node *, int);
+STATIC int evalsubshell(union node *, int);
+STATIC void expredir(union node *);
+STATIC int evalpipe(union node *, int);
+#ifdef notyet
+STATIC int evalcommand(union node *, int, struct backcmd *);
+#else
+STATIC int evalcommand(union node *, int);
+#endif
+STATIC int evalbltin(const struct builtincmd *, int, char **, int);
+STATIC int evalfun(struct funcnode *, int, char **, int);
+STATIC void prehash(union node *);
+STATIC int eprintlist(struct output *, struct strlist *, int);
+STATIC int bltincmd(int, char **);
+
+
+STATIC const struct builtincmd bltin = {
+	.name = nullstr,
+	.builtin = bltincmd,
+	.flags = BUILTIN_REGULAR,
+};
+
+
+/*
+ * Called to reset things after an exception.
+ */
+
+#ifdef mkinit
+INCLUDE "eval.h"
+
+EXITRESET {
+	if (savestatus >= 0) {
+		if (exception == EXEXIT || evalskip == SKIPFUNCDEF)
+			exitstatus = savestatus;
+		savestatus = -1;
+	}
+	evalskip = 0;
+	loopnest = 0;
+}
+#endif
+
+
+
+/*
+ * The eval commmand.
+ */
+
+static int evalcmd(int argc, char **argv, int flags)
+{
+        char *p;
+        char *concat;
+        char **ap;
+
+        if (argc > 1) {
+                p = argv[1];
+                if (argc > 2) {
+                        STARTSTACKSTR(concat);
+                        ap = argv + 2;
+                        for (;;) {
+                        	concat = stputs(p, concat);
+                                if ((p = *ap++) == NULL)
+                                        break;
+                                STPUTC(' ', concat);
+                        }
+                        STPUTC('\0', concat);
+                        p = grabstackstr(concat);
+                }
+                return evalstring(p, flags & EV_TESTED);
+        }
+        return 0;
+}
+
+
+/*
+ * Execute a command or commands contained in a string.
+ */
+
+int
+evalstring(char *s, int flags)
+{
+	union node *n;
+	struct stackmark smark;
+	int status;
+
+	s = sstrdup(s);
+	setinputstring(s);
+	setstackmark(&smark);
+
+	status = 0;
+	for (; (n = parsecmd(0)) != NEOF; popstackmark(&smark)) {
+		int i;
+
+		i = evaltree(n, flags & ~(parser_eof() ? 0 : EV_EXIT));
+		if (n)
+			status = i;
+
+		if (evalskip)
+			break;
+	}
+	popstackmark(&smark);
+	popfile();
+	stunalloc(s);
+
+	return status;
+}
+
+
+
+/*
+ * Evaluate a parse tree.  The value is left in the global variable
+ * exitstatus.
+ */
+
+int
+evaltree(union node *n, int flags)
+{
+	int checkexit = 0;
+	int (*evalfn)(union node *, int);
+	struct stackmark smark;
+	unsigned isor;
+	int status = 0;
+
+	setstackmark(&smark);
+
+	if (n == NULL) {
+		TRACE(("evaltree(NULL) called\n"));
+		goto out;
+	}
+
+	dotrap();
+
+#ifndef SMALL
+	displayhist = 1;	/* show history substitutions done with fc */
+#endif
+	TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
+	    getpid(), n, n->type, flags));
+	switch (n->type) {
+	default:
+#ifdef DEBUG
+		out1fmt("Node type = %d\n", n->type);
+#ifndef USE_GLIBC_STDIO
+		flushout(out1);
+#endif
+		break;
+#endif
+	case NNOT:
+		status = !evaltree(n->nnot.com, EV_TESTED);
+		goto setstatus;
+	case NREDIR:
+		errlinno = lineno = n->nredir.linno;
+		if (funcline)
+			lineno -= funcline - 1;
+		expredir(n->nredir.redirect);
+		pushredir(n->nredir.redirect);
+		status = redirectsafe(n->nredir.redirect, REDIR_PUSH) ?:
+			 evaltree(n->nredir.n, flags & EV_TESTED);
+		if (n->nredir.redirect)
+			popredir(0);
+		goto setstatus;
+	case NCMD:
+#ifdef notyet
+		if (eflag && !(flags & EV_TESTED))
+			checkexit = ~0;
+		status = evalcommand(n, flags, (struct backcmd *)NULL);
+		goto setstatus;
+#else
+		evalfn = evalcommand;
+checkexit:
+		if (eflag && !(flags & EV_TESTED))
+			checkexit = ~0;
+		goto calleval;
+#endif
+	case NFOR:
+		evalfn = evalfor;
+		goto calleval;
+	case NWHILE:
+	case NUNTIL:
+		evalfn = evalloop;
+		goto calleval;
+	case NSUBSHELL:
+	case NBACKGND:
+		evalfn = evalsubshell;
+		goto checkexit;
+	case NPIPE:
+		evalfn = evalpipe;
+		goto checkexit;
+	case NCASE:
+		evalfn = evalcase;
+		goto calleval;
+	case NAND:
+	case NOR:
+	case NSEMI:
+#if NAND + 1 != NOR
+#error NAND + 1 != NOR
+#endif
+#if NOR + 1 != NSEMI
+#error NOR + 1 != NSEMI
+#endif
+		isor = n->type - NAND;
+		status = evaltree(n->nbinary.ch1,
+				  (flags | ((isor >> 1) - 1)) & EV_TESTED);
+		if ((!status) == isor || evalskip)
+			break;
+		n = n->nbinary.ch2;
+evaln:
+		evalfn = evaltree;
+calleval:
+		status = evalfn(n, flags);
+		goto setstatus;
+	case NIF:
+		status = evaltree(n->nif.test, EV_TESTED);
+		if (evalskip)
+			break;
+		if (!status) {
+			n = n->nif.ifpart;
+			goto evaln;
+		} else if (n->nif.elsepart) {
+			n = n->nif.elsepart;
+			goto evaln;
+		}
+		status = 0;
+		goto setstatus;
+	case NDEFUN:
+		defun(n);
+setstatus:
+		exitstatus = status;
+		break;
+	}
+out:
+	dotrap();
+
+	if (checkexit & status)
+		goto exexit;
+
+	if (flags & EV_EXIT) {
+exexit:
+		exraise(EXEND);
+	}
+
+	popstackmark(&smark);
+
+	return exitstatus;
+}
+
+
+#if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
+STATIC
+#endif
+void evaltreenr(union node *n, int flags)
+#ifdef HAVE_ATTRIBUTE_ALIAS
+	__attribute__ ((alias("evaltree")));
+#else
+{
+	evaltree(n, flags);
+	abort();
+}
+#endif
+
+
+static int skiploop(void)
+{
+	int skip = evalskip;
+
+	switch (skip) {
+	case 0:
+		break;
+
+	case SKIPBREAK:
+	case SKIPCONT:
+		if (likely(--skipcount <= 0)) {
+			evalskip = 0;
+			break;
+		}
+
+		skip = SKIPBREAK;
+		break;
+	}
+
+	return skip;
+}
+
+
+STATIC int
+evalloop(union node *n, int flags)
+{
+	int skip;
+	int status;
+
+	loopnest++;
+	status = 0;
+	flags &= EV_TESTED;
+	do {
+		int i;
+
+		i = evaltree(n->nbinary.ch1, EV_TESTED);
+		skip = skiploop();
+		if (skip == SKIPFUNC)
+			status = i;
+		if (skip)
+			continue;
+		if (n->type != NWHILE)
+			i = !i;
+		if (i != 0)
+			break;
+		status = evaltree(n->nbinary.ch2, flags);
+		skip = skiploop();
+	} while (!(skip & ~SKIPCONT));
+	loopnest--;
+
+	return status;
+}
+
+
+
+STATIC int
+evalfor(union node *n, int flags)
+{
+	struct arglist arglist;
+	union node *argp;
+	struct strlist *sp;
+	int status;
+
+	errlinno = lineno = n->nfor.linno;
+	if (funcline)
+		lineno -= funcline - 1;
+
+	arglist.lastp = &arglist.list;
+	for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
+		expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
+	}
+	*arglist.lastp = NULL;
+
+	status = 0;
+	loopnest++;
+	flags &= EV_TESTED;
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		setvar(n->nfor.var, sp->text, 0);
+		status = evaltree(n->nfor.body, flags);
+		if (skiploop() & ~SKIPCONT)
+			break;
+	}
+	loopnest--;
+
+	return status;
+}
+
+
+
+STATIC int
+evalcase(union node *n, int flags)
+{
+	union node *cp;
+	union node *patp;
+	struct arglist arglist;
+	int status = 0;
+
+	errlinno = lineno = n->ncase.linno;
+	if (funcline)
+		lineno -= funcline - 1;
+
+	arglist.lastp = &arglist.list;
+	expandarg(n->ncase.expr, &arglist, EXP_TILDE);
+	for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
+		for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
+			if (casematch(patp, arglist.list->text)) {
+				/* Ensure body is non-empty as otherwise
+				 * EV_EXIT may prevent us from setting the
+				 * exit status.
+				 */
+				if (evalskip == 0 && cp->nclist.body) {
+					status = evaltree(cp->nclist.body,
+							  flags);
+				}
+				goto out;
+			}
+		}
+	}
+out:
+	return status;
+}
+
+
+
+/*
+ * Kick off a subshell to evaluate a tree.
+ */
+
+STATIC int
+evalsubshell(union node *n, int flags)
+{
+	struct job *jp;
+	int backgnd = (n->type == NBACKGND);
+	int status;
+
+	errlinno = lineno = n->nredir.linno;
+	if (funcline)
+		lineno -= funcline - 1;
+
+	expredir(n->nredir.redirect);
+	INTOFF;
+	if (!backgnd && flags & EV_EXIT && !have_traps()) {
+		forkreset();
+		goto nofork;
+	}
+	jp = makejob(n, 1);
+	if (forkshell(jp, n, backgnd) == 0) {
+		flags |= EV_EXIT;
+		if (backgnd)
+			flags &=~ EV_TESTED;
+nofork:
+		INTON;
+		redirect(n->nredir.redirect, 0);
+		evaltreenr(n->nredir.n, flags);
+		/* never returns */
+	}
+	status = 0;
+	if (! backgnd)
+		status = waitforjob(jp);
+	INTON;
+	return status;
+}
+
+
+
+/*
+ * Compute the names of the files in a redirection list.
+ */
+
+STATIC void
+expredir(union node *n)
+{
+	union node *redir;
+
+	for (redir = n ; redir ; redir = redir->nfile.next) {
+		struct arglist fn;
+		fn.lastp = &fn.list;
+		switch (redir->type) {
+		case NFROMTO:
+		case NFROM:
+		case NTO:
+		case NCLOBBER:
+		case NAPPEND:
+			expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
+			redir->nfile.expfname = fn.list->text;
+			break;
+		case NFROMFD:
+		case NTOFD:
+			if (redir->ndup.vname) {
+				expandarg(redir->ndup.vname, &fn, EXP_TILDE | EXP_REDIR);
+				fixredir(redir, fn.list->text, 1);
+			}
+			break;
+		}
+	}
+}
+
+
+
+/*
+ * Evaluate a pipeline.  All the processes in the pipeline are children
+ * of the process creating the pipeline.  (This differs from some versions
+ * of the shell, which make the last process in a pipeline the parent
+ * of all the rest.)
+ */
+
+STATIC int
+evalpipe(union node *n, int flags)
+{
+	struct job *jp;
+	struct nodelist *lp;
+	int pipelen;
+	int prevfd;
+	int pip[2];
+	int status = 0;
+
+	TRACE(("evalpipe(0x%lx) called\n", (long)n));
+	pipelen = 0;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
+		pipelen++;
+	flags |= EV_EXIT;
+	INTOFF;
+	jp = makejob(n, pipelen);
+	prevfd = -1;
+	for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+		prehash(lp->n);
+		pip[1] = -1;
+		if (lp->next) {
+			if (pipe(pip) < 0) {
+				close(prevfd);
+				sh_error("Pipe call failed");
+			}
+		}
+		if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
+			INTON;
+			if (pip[1] >= 0) {
+				close(pip[0]);
+			}
+			if (prevfd > 0) {
+				dup2(prevfd, 0);
+				close(prevfd);
+			}
+			if (pip[1] > 1) {
+				dup2(pip[1], 1);
+				close(pip[1]);
+			}
+			evaltreenr(lp->n, flags);
+			/* never returns */
+		}
+		if (prevfd >= 0)
+			close(prevfd);
+		prevfd = pip[0];
+		close(pip[1]);
+	}
+	if (n->npipe.backgnd == 0) {
+		status = waitforjob(jp);
+		TRACE(("evalpipe:  job done exit status %d\n", status));
+	}
+	INTON;
+
+	return status;
+}
+
+
+
+/*
+ * Execute a command inside back quotes.  If it's a builtin command, we
+ * want to save its output in a block obtained from malloc.  Otherwise
+ * we fork off a subprocess and get the output of the command via a pipe.
+ * Should be called with interrupts off.
+ */
+
+void
+evalbackcmd(union node *n, struct backcmd *result)
+{
+	int pip[2];
+	struct job *jp;
+
+	result->fd = -1;
+	result->buf = NULL;
+	result->nleft = 0;
+	result->jp = NULL;
+	if (n == NULL) {
+		goto out;
+	}
+
+	if (pipe(pip) < 0)
+		sh_error("Pipe call failed");
+	jp = makejob(n, 1);
+	if (forkshell(jp, n, FORK_NOJOB) == 0) {
+		FORCEINTON;
+		close(pip[0]);
+		if (pip[1] != 1) {
+			dup2(pip[1], 1);
+			close(pip[1]);
+		}
+		ifsfree();
+		evaltreenr(n, EV_EXIT);
+		/* NOTREACHED */
+	}
+	close(pip[1]);
+	result->fd = pip[0];
+	result->jp = jp;
+
+out:
+	TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
+		result->fd, result->buf, result->nleft, result->jp));
+}
+
+static struct strlist *fill_arglist(struct arglist *arglist,
+				    union node **argpp)
+{
+	struct strlist **lastp = arglist->lastp;
+	union node *argp;
+
+	while ((argp = *argpp)) {
+		expandarg(argp, arglist, EXP_FULL | EXP_TILDE);
+		*argpp = argp->narg.next;
+		if (*lastp)
+			break;
+	}
+
+	return *lastp;
+}
+
+static int parse_command_args(struct arglist *arglist, union node **argpp,
+			      const char **path)
+{
+	struct strlist *sp = arglist->list;
+	char *cp, c;
+
+	for (;;) {
+		sp = unlikely(sp->next) ? sp->next :
+					  fill_arglist(arglist, argpp);
+		if (!sp)
+			return 0;
+		cp = sp->text;
+		if (*cp++ != '-')
+			break;
+		if (!(c = *cp++))
+			break;
+		if (c == '-' && !*cp) {
+			if (likely(!sp->next) && !fill_arglist(arglist, argpp))
+				return 0;
+			sp = sp->next;
+			break;
+		}
+		do {
+			switch (c) {
+			case 'p':
+				*path = defpath;
+				break;
+			default:
+				/* run 'typecmd' for other options */
+				return 0;
+			}
+		} while ((c = *cp++));
+	}
+
+	arglist->list = sp;
+	return DO_NOFUNC;
+}
+
+/*
+ * Execute a simple command.
+ */
+
+STATIC int
+#ifdef notyet
+evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
+#else
+evalcommand(union node *cmd, int flags)
+#endif
+{
+	struct localvar_list *localvar_stop;
+	struct parsefile *file_stop;
+	struct redirtab *redir_stop;
+	union node *argp;
+	struct arglist arglist;
+	struct arglist varlist;
+	char **argv;
+	int argc;
+	struct strlist *osp;
+	struct strlist *sp;
+#ifdef notyet
+	int pip[2];
+#endif
+	struct cmdentry cmdentry;
+	struct job *jp;
+	char *lastarg;
+	const char *path;
+	int spclbltin;
+	int cmd_flag;
+	int execcmd;
+	int status;
+	char **nargv;
+	int vflags;
+	int vlocal;
+
+	errlinno = lineno = cmd->ncmd.linno;
+	if (funcline)
+		lineno -= funcline - 1;
+
+	/* First expand the arguments. */
+	TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
+	file_stop = parsefile;
+	back_exitstatus = 0;
+
+	cmdentry.cmdtype = CMDBUILTIN;
+	cmdentry.u.cmd = &bltin;
+	varlist.lastp = &varlist.list;
+	*varlist.lastp = NULL;
+	arglist.lastp = &arglist.list;
+	*arglist.lastp = NULL;
+
+	cmd_flag = 0;
+	execcmd = 0;
+	spclbltin = -1;
+	vflags = 0;
+	vlocal = 0;
+	path = NULL;
+
+	argc = 0;
+	argp = cmd->ncmd.args;
+	if ((osp = fill_arglist(&arglist, &argp))) {
+		int pseudovarflag = 0;
+
+		for (;;) {
+			find_command(arglist.list->text, &cmdentry,
+				     cmd_flag | DO_REGBLTIN, pathval());
+
+			vlocal++;
+
+			/* implement bltin and command here */
+			if (cmdentry.cmdtype != CMDBUILTIN)
+				break;
+
+			pseudovarflag = cmdentry.u.cmd->flags & BUILTIN_ASSIGN;
+			if (likely(spclbltin < 0)) {
+				spclbltin =
+					cmdentry.u.cmd->flags &
+					BUILTIN_SPECIAL
+				;
+				vlocal = spclbltin ^ BUILTIN_SPECIAL;
+			}
+			execcmd = cmdentry.u.cmd == EXECCMD;
+			if (likely(cmdentry.u.cmd != COMMANDCMD))
+				break;
+
+			cmd_flag = parse_command_args(&arglist, &argp, &path);
+			if (!cmd_flag)
+				break;
+		}
+
+		for (; argp; argp = argp->narg.next)
+			expandarg(argp, &arglist,
+				  pseudovarflag &&
+				  isassignment(argp->narg.text) ?
+				  EXP_VARTILDE : EXP_FULL | EXP_TILDE);
+
+		for (sp = arglist.list; sp; sp = sp->next)
+			argc++;
+
+		if (execcmd && argc > 1)
+			vflags = VEXPORT;
+	}
+
+	localvar_stop = pushlocalvars(vlocal);
+
+	/* Reserve one extra spot at the front for shellexec. */
+	nargv = stalloc(sizeof (char *) * (argc + 2));
+	argv = ++nargv;
+	for (sp = arglist.list ; sp ; sp = sp->next) {
+		TRACE(("evalcommand arg: %s\n", sp->text));
+		*nargv++ = sp->text;
+	}
+	*nargv = NULL;
+
+	lastarg = NULL;
+	if (iflag && funcline == 0 && argc > 0)
+		lastarg = nargv[-1];
+
+	preverrout.fd = 2;
+	expredir(cmd->ncmd.redirect);
+	redir_stop = pushredir(cmd->ncmd.redirect);
+	status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
+
+	if (unlikely(status)) {
+bail:
+		exitstatus = status;
+
+		/* We have a redirection error. */
+		if (spclbltin > 0)
+			exraise(EXERROR);
+
+		goto out;
+	}
+
+	for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
+		struct strlist **spp;
+
+		spp = varlist.lastp;
+		expandarg(argp, &varlist, EXP_VARTILDE);
+
+		if (vlocal)
+			mklocal((*spp)->text, VEXPORT);
+		else
+			setvareq((*spp)->text, vflags);
+	}
+
+	/* Print the command if xflag is set. */
+	if (xflag) {
+		struct output *out;
+		int sep;
+
+		out = &preverrout;
+		outstr(expandstr(ps4val()), out);
+		sep = 0;
+		sep = eprintlist(out, varlist.list, sep);
+		eprintlist(out, osp, sep);
+		outcslow('\n', out);
+#ifdef FLUSHERR
+		flushout(out);
+#endif
+	}
+
+	/* Now locate the command. */
+	if (cmdentry.cmdtype != CMDBUILTIN ||
+	    !(cmdentry.u.cmd->flags & BUILTIN_REGULAR)) {
+		path = unlikely(path) ? path : pathval();
+		find_command(argv[0], &cmdentry, cmd_flag | DO_ERR, path);
+	}
+
+	jp = NULL;
+
+	/* Execute the command. */
+	switch (cmdentry.cmdtype) {
+	case CMDUNKNOWN:
+		status = 127;
+#ifdef FLUSHERR
+		flushout(&errout);
+#endif
+		goto bail;
+
+	default:
+		/* Fork off a child process if necessary. */
+		if (!(flags & EV_EXIT) || have_traps()) {
+			INTOFF;
+			jp = vforkexec(cmd, argv, path, cmdentry.u.index);
+			break;
+		}
+		shellexec(argv, path, cmdentry.u.index);
+		/* NOTREACHED */
+
+	case CMDBUILTIN:
+		if (evalbltin(cmdentry.u.cmd, argc, argv, flags) &&
+		    !(exception == EXERROR && spclbltin <= 0)) {
+raise:
+			longjmp(handler->loc, 1);
+		}
+		break;
+
+	case CMDFUNCTION:
+		if (evalfun(cmdentry.u.func, argc, argv, flags))
+			goto raise;
+		break;
+	}
+
+	status = waitforjob(jp);
+	FORCEINTON;
+
+out:
+	if (cmd->ncmd.redirect)
+		popredir(execcmd);
+	unwindredir(redir_stop);
+	unwindfiles(file_stop);
+	unwindlocalvars(localvar_stop);
+	if (lastarg)
+		/* dsl: I think this is intended to be used to support
+		 * '_' in 'vi' command mode during line editing...
+		 * However I implemented that within libedit itself.
+		 */
+		setvar("_", lastarg, 0);
+
+	return status;
+}
+
+STATIC int
+evalbltin(const struct builtincmd *cmd, int argc, char **argv, int flags)
+{
+	char *volatile savecmdname;
+	struct jmploc *volatile savehandler;
+	struct jmploc jmploc;
+	int status;
+	int i;
+
+	savecmdname = commandname;
+	savehandler = handler;
+	if ((i = setjmp(jmploc.loc)))
+		goto cmddone;
+	handler = &jmploc;
+	commandname = argv[0];
+	argptr = argv + 1;
+	optptr = NULL;			/* initialize nextopt */
+	if (cmd == EVALCMD)
+		status = evalcmd(argc, argv, flags);
+	else
+		status = (*cmd->builtin)(argc, argv);
+	flushall();
+	if (outerr(out1))
+		sh_warnx("%s: I/O error", commandname);
+	status |= outerr(out1);
+	exitstatus = status;
+cmddone:
+	freestdout();
+	commandname = savecmdname;
+	handler = savehandler;
+
+	return i;
+}
+
+STATIC int
+evalfun(struct funcnode *func, int argc, char **argv, int flags)
+{
+	volatile struct shparam saveparam;
+	struct jmploc *volatile savehandler;
+	struct jmploc jmploc;
+	int e;
+	int savefuncline;
+	int saveloopnest;
+
+	saveparam = shellparam;
+	savefuncline = funcline;
+	saveloopnest = loopnest;
+	savehandler = handler;
+	if ((e = setjmp(jmploc.loc))) {
+		goto funcdone;
+	}
+	INTOFF;
+	handler = &jmploc;
+	shellparam.malloc = 0;
+	func->count++;
+	funcline = func->n.ndefun.linno;
+	loopnest = 0;
+	INTON;
+	shellparam.nparam = argc - 1;
+	shellparam.p = argv + 1;
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+	evaltree(func->n.ndefun.body, flags & EV_TESTED);
+funcdone:
+	INTOFF;
+	loopnest = saveloopnest;
+	funcline = savefuncline;
+	freefunc(func);
+	freeparam(&shellparam);
+	shellparam = saveparam;
+	handler = savehandler;
+	INTON;
+	evalskip &= ~(SKIPFUNC | SKIPFUNCDEF);
+	return e;
+}
+
+
+/*
+ * Search for a command.  This is called before we fork so that the
+ * location of the command will be available in the parent as well as
+ * the child.  The check for "goodname" is an overly conservative
+ * check that the name will not be subject to expansion.
+ */
+
+STATIC void
+prehash(union node *n)
+{
+	struct cmdentry entry;
+
+	if (n->type == NCMD && n->ncmd.args)
+		if (goodname(n->ncmd.args->narg.text))
+			find_command(n->ncmd.args->narg.text, &entry, 0,
+				     pathval());
+}
+
+
+
+/*
+ * Builtin commands.  Builtin commands whose functions are closely
+ * tied to evaluation are implemented here.
+ */
+
+/*
+ * No command given.
+ */
+
+STATIC int
+bltincmd(int argc, char **argv)
+{
+	/*
+	 * Preserve exitstatus of a previous possible redirection
+	 * as POSIX mandates
+	 */
+	return back_exitstatus;
+}
+
+
+/*
+ * Handle break and continue commands.  Break, continue, and return are
+ * all handled by setting the evalskip flag.  The evaluation routines
+ * above all check this flag, and if it is set they start skipping
+ * commands rather than executing them.  The variable skipcount is
+ * the number of loops to break/continue, or the number of function
+ * levels to return.  (The latter is always 1.)  It should probably
+ * be an error to break out of more loops than exist, but it isn't
+ * in the standard shell so we don't make it one here.
+ */
+
+int
+breakcmd(int argc, char **argv)
+{
+	int n = argc > 1 ? number(argv[1]) : 1;
+
+	if (n <= 0)
+		badnum(argv[1]);
+	if (n > loopnest)
+		n = loopnest;
+	if (n > 0) {
+		evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
+		skipcount = n;
+	}
+	return 0;
+}
+
+
+/*
+ * The return command.
+ */
+
+int
+returncmd(int argc, char **argv)
+{
+	int skip;
+	int status;
+
+	/*
+	 * If called outside a function, do what ksh does;
+	 * skip the rest of the file.
+	 */
+	if (argv[1]) {
+		skip = SKIPFUNC;
+		status = number(argv[1]);
+	} else {
+		skip = SKIPFUNCDEF;
+		status = exitstatus;
+	}
+	evalskip = skip;
+
+	return status;
+}
+
+
+int
+falsecmd(int argc, char **argv)
+{
+	return 1;
+}
+
+
+int
+truecmd(int argc, char **argv)
+{
+	return 0;
+}
+
+
+int
+execcmd(int argc, char **argv)
+{
+	if (argc > 1) {
+		iflag = 0;		/* exit on error */
+		mflag = 0;
+		optschanged();
+		shellexec(argv + 1, pathval(), 0);
+	}
+	return 0;
+}
+
+
+STATIC int
+eprintlist(struct output *out, struct strlist *sp, int sep)
+{
+	while (sp) {
+		const char *p;
+
+		p = " %s";
+		p += (1 - sep);
+		sep |= 1;
+		outfmt(out, p, sp->text);
+		sp = sp->next;
+	}
+
+	return sep;
+}
diff --git a/bin/dash/src/eval.h b/bin/dash/src/eval.h
new file mode 100644
index 00000000..63e7d865
--- /dev/null
+++ b/bin/dash/src/eval.h
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)eval.h	8.2 (Berkeley) 5/4/95
+ */
+
+extern char *commandname;	/* currently executing command */
+extern int exitstatus;		/* exit status of last command */
+extern int back_exitstatus;	/* exit status of backquoted command */
+extern int savestatus;		/* exit status of last command outside traps */
+
+
+struct backcmd {		/* result of evalbackcmd */
+	int fd;			/* file descriptor to read from */
+	char *buf;		/* buffer */
+	int nleft;		/* number of chars in buffer */
+	struct job *jp;		/* job structure for command */
+};
+
+/* flags in argument to evaltree */
+#define EV_EXIT 01		/* exit after evaluating tree */
+#define EV_TESTED 02		/* exit status is checked; ignore -e flag */
+
+int evalstring(char *, int);
+union node;	/* BLETCH for ansi C */
+int evaltree(union node *, int);
+void evalbackcmd(union node *, struct backcmd *);
+
+extern int evalskip;
+
+/* reasons for skipping commands (see comment on breakcmd routine) */
+#define SKIPBREAK	(1 << 0)
+#define SKIPCONT	(1 << 1)
+#define SKIPFUNC	(1 << 2)
+#define SKIPFUNCDEF	(1 << 3)
diff --git a/bin/dash/src/exec.c b/bin/dash/src/exec.c
new file mode 100644
index 00000000..87354d49
--- /dev/null
+++ b/bin/dash/src/exec.c
@@ -0,0 +1,908 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+/*
+ * When commands are first encountered, they are entered in a hash table.
+ * This ensures that a full path search will not have to be done for them
+ * on each invocation.
+ *
+ * We should investigate converting to a linear search, even though that
+ * would make the command name "hash" a misnomer.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "parser.h"
+#include "redir.h"
+#include "eval.h"
+#include "exec.h"
+#include "builtins.h"
+#include "var.h"
+#include "options.h"
+#include "output.h"
+#include "syntax.h"
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+#include "show.h"
+#include "jobs.h"
+#include "alias.h"
+#include "system.h"
+
+
+#define CMDTABLESIZE 31		/* should be prime */
+#define ARB 1			/* actual size determined at run time */
+
+
+
+struct tblentry {
+	struct tblentry *next;	/* next entry in hash chain */
+	union param param;	/* definition of builtin function */
+	short cmdtype;		/* index identifying command */
+	char rehash;		/* if set, cd done since entry created */
+	char cmdname[ARB];	/* name of command */
+};
+
+
+STATIC struct tblentry *cmdtable[CMDTABLESIZE];
+STATIC int builtinloc = -1;		/* index in path of %builtin, or -1 */
+
+
+STATIC void tryexec(char *, char **, char **);
+STATIC void printentry(struct tblentry *);
+STATIC void clearcmdentry(void);
+STATIC struct tblentry *cmdlookup(const char *, int);
+STATIC void delete_cmd_entry(void);
+STATIC void addcmdentry(char *, struct cmdentry *);
+STATIC int describe_command(struct output *, char *, const char *, int);
+
+
+/*
+ * Exec a program.  Never returns.  If you change this routine, you may
+ * have to change the find_command routine as well.
+ */
+
+void
+shellexec(char **argv, const char *path, int idx)
+{
+	char *cmdname;
+	int e;
+	char **envp;
+	int exerrno;
+
+	envp = environment();
+	if (strchr(argv[0], '/') != NULL) {
+		tryexec(argv[0], argv, envp);
+		e = errno;
+	} else {
+		e = ENOENT;
+		while (padvance(&path, argv[0]) >= 0) {
+			cmdname = stackblock();
+			if (--idx < 0 && pathopt == NULL) {
+				tryexec(cmdname, argv, envp);
+				if (errno != ENOENT && errno != ENOTDIR)
+					e = errno;
+			}
+		}
+	}
+
+	/* Map to POSIX errors */
+	switch (e) {
+	default:
+		exerrno = 126;
+		break;
+	case ELOOP:
+	case ENAMETOOLONG:
+	case ENOENT:
+	case ENOTDIR:
+		exerrno = 127;
+		break;
+	}
+	exitstatus = exerrno;
+	TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
+		argv[0], e, suppressint ));
+	exerror(EXEND, "%s: %s", argv[0], errmsg(e, E_EXEC));
+	/* NOTREACHED */
+}
+
+
+STATIC void
+tryexec(char *cmd, char **argv, char **envp)
+{
+	char *const path_bshell = _PATH_BSHELL;
+
+repeat:
+#ifdef SYSV
+	do {
+		execve(cmd, argv, envp);
+	} while (errno == EINTR);
+#else
+	execve(cmd, argv, envp);
+#endif
+	if (cmd != path_bshell && errno == ENOEXEC) {
+		*argv-- = cmd;
+		*argv = cmd = path_bshell;
+		goto repeat;
+	}
+}
+
+static const char *legal_pathopt(const char *opt, const char *term, int magic)
+{
+	switch (magic) {
+	case 0:
+		opt = NULL;
+		break;
+
+	case 1:
+		opt = prefix(opt, "builtin") ?: prefix(opt, "func");
+		break;
+
+	default:
+		opt += strcspn(opt, term);
+		break;
+	}
+
+	if (opt && *opt == '%')
+		opt++;
+
+	return opt;
+}
+
+/*
+ * Do a path search.  The variable path (passed by reference) should be
+ * set to the start of the path before the first call; padvance will update
+ * this value as it proceeds.  Successive calls to padvance will return
+ * the possible path expansions in sequence.  If an option (indicated by
+ * a percent sign) appears in the path entry then the global variable
+ * pathopt will be set to point to it; otherwise pathopt will be set to
+ * NULL.
+ *
+ * If magic is 0 then pathopt recognition will be disabled.  If magic is
+ * 1 we shall recognise %builtin/%func.  Otherwise we shall accept any
+ * pathopt.
+ */
+
+const char *pathopt;
+
+int padvance_magic(const char **path, const char *name, int magic)
+{
+	const char *term = "%:";
+	const char *lpathopt;
+	const char *p;
+	char *q;
+	const char *start;
+	size_t qlen;
+	size_t len;
+
+	if (*path == NULL)
+		return -1;
+
+	lpathopt = NULL;
+	start = *path;
+
+	if (*start == '%' && (p = legal_pathopt(start + 1, term, magic))) {
+		lpathopt = start + 1;
+		start = p;
+		term = ":";
+	}
+
+	len = strcspn(start, term);
+	p = start + len;
+
+	if (*p == '%') {
+		size_t extra = strchrnul(p, ':') - p;
+
+		if (legal_pathopt(p + 1, term, magic))
+			lpathopt = p + 1;
+		else
+			len += extra;
+
+		p += extra;
+	}
+
+	pathopt = lpathopt;
+	*path = *p == ':' ? p + 1 : NULL;
+
+	/* "2" is for '/' and '\0' */
+	qlen = len + strlen(name) + 2;
+	q = growstackto(qlen);
+
+	if (likely(len)) {
+		q = mempcpy(q, start, len);
+		*q++ = '/';
+	}
+	strcpy(q, name);
+
+	return qlen;
+}
+
+
+
+/*** Command hashing code ***/
+
+
+int
+hashcmd(int argc, char **argv)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+	int c;
+	struct cmdentry entry;
+	char *name;
+
+	while ((c = nextopt("r")) != '\0') {
+		clearcmdentry();
+		return 0;
+	}
+	if (*argptr == NULL) {
+		for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+			for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+				if (cmdp->cmdtype == CMDNORMAL)
+					printentry(cmdp);
+			}
+		}
+		return 0;
+	}
+	c = 0;
+	while ((name = *argptr) != NULL) {
+		if ((cmdp = cmdlookup(name, 0)) &&
+		    (cmdp->cmdtype == CMDNORMAL ||
+		     (cmdp->cmdtype == CMDBUILTIN &&
+		      !(cmdp->param.cmd->flags & BUILTIN_REGULAR) &&
+		      builtinloc > 0)))
+			delete_cmd_entry();
+		find_command(name, &entry, DO_ERR, pathval());
+		if (entry.cmdtype == CMDUNKNOWN)
+			c = 1;
+		argptr++;
+	}
+	return c;
+}
+
+
+STATIC void
+printentry(struct tblentry *cmdp)
+{
+	int idx;
+	const char *path;
+	char *name;
+
+	idx = cmdp->param.index;
+	path = pathval();
+	do {
+		padvance(&path, cmdp->cmdname);
+	} while (--idx >= 0);
+	name = stackblock();
+	out1str(name);
+	out1fmt(snlfmt, cmdp->rehash ? "*" : nullstr);
+}
+
+
+
+/*
+ * Resolve a command name.  If you change this routine, you may have to
+ * change the shellexec routine as well.
+ */
+
+void
+find_command(char *name, struct cmdentry *entry, int act, const char *path)
+{
+	struct tblentry *cmdp;
+	int idx;
+	int prev;
+	char *fullname;
+	struct stat64 statb;
+	int e;
+	int updatetbl;
+	struct builtincmd *bcmd;
+	int len;
+
+	/* If name contains a slash, don't use PATH or hash table */
+	if (strchr(name, '/') != NULL) {
+		entry->u.index = -1;
+		if (act & DO_ABS) {
+			while (stat64(name, &statb) < 0) {
+#ifdef SYSV
+				if (errno == EINTR)
+					continue;
+#endif
+				entry->cmdtype = CMDUNKNOWN;
+				return;
+			}
+		}
+		entry->cmdtype = CMDNORMAL;
+		return;
+	}
+
+	updatetbl = (path == pathval());
+	if (!updatetbl)
+		act |= DO_ALTPATH;
+
+	/* If name is in the table, check answer will be ok */
+	if ((cmdp = cmdlookup(name, 0)) != NULL) {
+		int bit;
+
+		switch (cmdp->cmdtype) {
+		default:
+#if DEBUG
+			abort();
+#endif
+		case CMDNORMAL:
+			bit = DO_ALTPATH | DO_REGBLTIN;
+			break;
+		case CMDFUNCTION:
+			bit = DO_NOFUNC;
+			break;
+		case CMDBUILTIN:
+			bit = cmdp->param.cmd->flags & BUILTIN_REGULAR ?
+			      0 : DO_REGBLTIN;
+			break;
+		}
+		if (act & bit) {
+			if (act & bit & DO_REGBLTIN)
+				goto fail;
+
+			updatetbl = 0;
+			cmdp = NULL;
+		} else if (cmdp->rehash == 0)
+			/* if not invalidated by cd, we're done */
+			goto success;
+	}
+
+	/* If %builtin not in path, check for builtin next */
+	bcmd = find_builtin(name);
+	if (bcmd && ((bcmd->flags & BUILTIN_REGULAR) | (act & DO_ALTPATH) |
+		     (builtinloc <= 0)))
+		goto builtin_success;
+
+	if (act & DO_REGBLTIN)
+		goto fail;
+
+	/* We have to search path. */
+	prev = -1;		/* where to start */
+	if (cmdp && cmdp->rehash) {	/* doing a rehash */
+		if (cmdp->cmdtype == CMDBUILTIN)
+			prev = builtinloc;
+		else
+			prev = cmdp->param.index;
+	}
+
+	e = ENOENT;
+	idx = -1;
+loop:
+	while ((len = padvance(&path, name)) >= 0) {
+		const char *lpathopt = pathopt;
+
+		fullname = stackblock();
+		idx++;
+		if (lpathopt) {
+			if (*lpathopt == 'b') {
+				if (bcmd)
+					goto builtin_success;
+				continue;
+			} else if (!(act & DO_NOFUNC)) {
+				/* handled below */
+			} else {
+				/* ignore unimplemented options */
+				continue;
+			}
+		}
+		/* if rehash, don't redo absolute path names */
+		if (fullname[0] == '/' && idx <= prev) {
+			if (idx < prev)
+				continue;
+			TRACE(("searchexec \"%s\": no change\n", name));
+			goto success;
+		}
+		while (stat64(fullname, &statb) < 0) {
+#ifdef SYSV
+			if (errno == EINTR)
+				continue;
+#endif
+			if (errno != ENOENT && errno != ENOTDIR)
+				e = errno;
+			goto loop;
+		}
+		e = EACCES;	/* if we fail, this will be the error */
+		if (!S_ISREG(statb.st_mode))
+			continue;
+		if (lpathopt) {		/* this is a %func directory */
+			stalloc(len);
+			readcmdfile(fullname);
+			if ((cmdp = cmdlookup(name, 0)) == NULL ||
+			    cmdp->cmdtype != CMDFUNCTION)
+				sh_error("%s not defined in %s", name,
+					 fullname);
+			stunalloc(fullname);
+			goto success;
+		}
+#ifdef notdef
+		/* XXX this code stops root executing stuff, and is buggy
+		   if you need a group from the group list. */
+		if (statb.st_uid == geteuid()) {
+			if ((statb.st_mode & 0100) == 0)
+				goto loop;
+		} else if (statb.st_gid == getegid()) {
+			if ((statb.st_mode & 010) == 0)
+				goto loop;
+		} else {
+			if ((statb.st_mode & 01) == 0)
+				goto loop;
+		}
+#endif
+		TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
+		if (!updatetbl) {
+			entry->cmdtype = CMDNORMAL;
+			entry->u.index = idx;
+			return;
+		}
+		INTOFF;
+		cmdp = cmdlookup(name, 1);
+		cmdp->cmdtype = CMDNORMAL;
+		cmdp->param.index = idx;
+		INTON;
+		goto success;
+	}
+
+	/* We failed.  If there was an entry for this command, delete it */
+	if (cmdp && updatetbl)
+		delete_cmd_entry();
+	if (act & DO_ERR)
+		sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
+fail:
+	entry->cmdtype = CMDUNKNOWN;
+	return;
+
+builtin_success:
+	if (!updatetbl) {
+		entry->cmdtype = CMDBUILTIN;
+		entry->u.cmd = bcmd;
+		return;
+	}
+	INTOFF;
+	cmdp = cmdlookup(name, 1);
+	cmdp->cmdtype = CMDBUILTIN;
+	cmdp->param.cmd = bcmd;
+	INTON;
+success:
+	cmdp->rehash = 0;
+	entry->cmdtype = cmdp->cmdtype;
+	entry->u = cmdp->param;
+}
+
+
+
+/*
+ * Search the table of builtin commands.
+ */
+
+struct builtincmd *
+find_builtin(const char *name)
+{
+	struct builtincmd *bp;
+
+	bp = bsearch(
+		&name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
+		pstrcmp
+	);
+	return bp;
+}
+
+
+
+/*
+ * Called when a cd is done.  Marks all commands so the next time they
+ * are executed they will be rehashed.
+ */
+
+void
+hashcd(void)
+{
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
+		for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+			if (cmdp->cmdtype == CMDNORMAL || (
+				cmdp->cmdtype == CMDBUILTIN &&
+				!(cmdp->param.cmd->flags & BUILTIN_REGULAR) &&
+				builtinloc > 0
+			))
+				cmdp->rehash = 1;
+		}
+	}
+}
+
+
+
+/*
+ * Fix command hash table when PATH changed.
+ * Called before PATH is changed.  The argument is the new value of PATH;
+ * pathval() still returns the old value at this point.
+ * Called with interrupts off.
+ */
+
+void
+changepath(const char *newval)
+{
+	const char *new;
+	int idx;
+	int bltin;
+
+	new = newval;
+	idx = 0;
+	bltin = -1;
+	for (;;) {
+		if (*new == '%' && prefix(new + 1, "builtin")) {
+			bltin = idx;
+			break;
+		}
+		new = strchr(new, ':');
+		if (!new)
+			break;
+		idx++;
+		new++;
+	}
+	builtinloc = bltin;
+	clearcmdentry();
+}
+
+
+/*
+ * Clear out command entries.  The argument specifies the first entry in
+ * PATH which has changed.
+ */
+
+STATIC void
+clearcmdentry(void)
+{
+	struct tblentry **tblp;
+	struct tblentry **pp;
+	struct tblentry *cmdp;
+
+	INTOFF;
+	for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
+		pp = tblp;
+		while ((cmdp = *pp) != NULL) {
+			if (cmdp->cmdtype == CMDNORMAL ||
+			    (cmdp->cmdtype == CMDBUILTIN &&
+			     !(cmdp->param.cmd->flags & BUILTIN_REGULAR) &&
+			     builtinloc > 0)) {
+				*pp = cmdp->next;
+				ckfree(cmdp);
+			} else {
+				pp = &cmdp->next;
+			}
+		}
+	}
+	INTON;
+}
+
+
+
+/*
+ * Locate a command in the command hash table.  If "add" is nonzero,
+ * add the command to the table if it is not already present.  The
+ * variable "lastcmdentry" is set to point to the address of the link
+ * pointing to the entry, so that delete_cmd_entry can delete the
+ * entry.
+ *
+ * Interrupts must be off if called with add != 0.
+ */
+
+struct tblentry **lastcmdentry;
+
+
+STATIC struct tblentry *
+cmdlookup(const char *name, int add)
+{
+	unsigned int hashval;
+	const char *p;
+	struct tblentry *cmdp;
+	struct tblentry **pp;
+
+	p = name;
+	hashval = (unsigned char)*p << 4;
+	while (*p)
+		hashval += (unsigned char)*p++;
+	hashval &= 0x7FFF;
+	pp = &cmdtable[hashval % CMDTABLESIZE];
+	for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
+		if (equal(cmdp->cmdname, name))
+			break;
+		pp = &cmdp->next;
+	}
+	if (add && cmdp == NULL) {
+		cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
+					+ strlen(name) + 1);
+		cmdp->next = NULL;
+		cmdp->cmdtype = CMDUNKNOWN;
+		strcpy(cmdp->cmdname, name);
+	}
+	lastcmdentry = pp;
+	return cmdp;
+}
+
+/*
+ * Delete the command entry returned on the last lookup.
+ */
+
+STATIC void
+delete_cmd_entry(void)
+{
+	struct tblentry *cmdp;
+
+	INTOFF;
+	cmdp = *lastcmdentry;
+	*lastcmdentry = cmdp->next;
+	if (cmdp->cmdtype == CMDFUNCTION)
+		freefunc(cmdp->param.func);
+	ckfree(cmdp);
+	INTON;
+}
+
+
+
+#ifdef notdef
+void
+getcmdentry(char *name, struct cmdentry *entry)
+{
+	struct tblentry *cmdp = cmdlookup(name, 0);
+
+	if (cmdp) {
+		entry->u = cmdp->param;
+		entry->cmdtype = cmdp->cmdtype;
+	} else {
+		entry->cmdtype = CMDUNKNOWN;
+		entry->u.index = 0;
+	}
+}
+#endif
+
+
+/*
+ * Add a new command entry, replacing any existing command entry for
+ * the same name - except special builtins.
+ */
+
+STATIC void
+addcmdentry(char *name, struct cmdentry *entry)
+{
+	struct tblentry *cmdp;
+
+	cmdp = cmdlookup(name, 1);
+	if (cmdp->cmdtype == CMDFUNCTION) {
+		freefunc(cmdp->param.func);
+	}
+	cmdp->cmdtype = entry->cmdtype;
+	cmdp->param = entry->u;
+	cmdp->rehash = 0;
+}
+
+
+/*
+ * Define a shell function.
+ */
+
+void
+defun(union node *func)
+{
+	struct cmdentry entry;
+
+	INTOFF;
+	entry.cmdtype = CMDFUNCTION;
+	entry.u.func = copyfunc(func);
+	addcmdentry(func->ndefun.text, &entry);
+	INTON;
+}
+
+
+/*
+ * Delete a function if it exists.
+ */
+
+void
+unsetfunc(const char *name)
+{
+	struct tblentry *cmdp;
+
+	if ((cmdp = cmdlookup(name, 0)) != NULL &&
+	    cmdp->cmdtype == CMDFUNCTION)
+		delete_cmd_entry();
+}
+
+/*
+ * Locate and print what a word is...
+ */
+
+int
+typecmd(int argc, char **argv)
+{
+	int i;
+	int err = 0;
+
+	for (i = 1; i < argc; i++) {
+		err |= describe_command(out1, argv[i], NULL, 1);
+	}
+	return err;
+}
+
+STATIC int
+describe_command(out, command, path, verbose)
+	struct output *out;
+	char *command;
+	const char *path;
+	int verbose;
+{
+	struct cmdentry entry;
+	struct tblentry *cmdp;
+	const struct alias *ap;
+
+	if (verbose) {
+		outstr(command, out);
+	}
+
+	/* First look at the keywords */
+	if (findkwd(command)) {
+		outstr(verbose ? " is a shell keyword" : command, out);
+		goto out;
+	}
+
+	/* Then look at the aliases */
+	if ((ap = lookupalias(command, 0)) != NULL) {
+		if (verbose) {
+			outfmt(out, " is an alias for %s", ap->val);
+		} else {
+			outstr("alias ", out);
+			printalias(ap);
+			return 0;
+		}
+		goto out;
+	}
+
+	/* Then if the standard search path is used, check if it is
+	 * a tracked alias.
+	 */
+	if (path == NULL) {
+		path = pathval();
+		cmdp = cmdlookup(command, 0);
+	} else {
+		cmdp = NULL;
+	}
+
+	if (cmdp != NULL) {
+		entry.cmdtype = cmdp->cmdtype;
+		entry.u = cmdp->param;
+	} else {
+		/* Finally use brute force */
+		find_command(command, &entry, DO_ABS, path);
+	}
+
+	switch (entry.cmdtype) {
+	case CMDNORMAL: {
+		int j = entry.u.index;
+		char *p;
+		if (j == -1) {
+			p = command;
+		} else {
+			do {
+				padvance(&path, command);
+			} while (--j >= 0);
+			p = stackblock();
+		}
+		if (verbose) {
+			outfmt(
+				out, " is%s %s",
+				cmdp ? " a tracked alias for" : nullstr, p
+			);
+		} else {
+			outstr(p, out);
+		}
+		break;
+	}
+
+	case CMDFUNCTION:
+		if (verbose) {
+			outstr(" is a shell function", out);
+		} else {
+			outstr(command, out);
+		}
+		break;
+
+	case CMDBUILTIN:
+		if (verbose) {
+			outfmt(
+				out, " is a %sshell builtin",
+				entry.u.cmd->flags & BUILTIN_SPECIAL ?
+					"special " : nullstr
+			);
+		} else {
+			outstr(command, out);
+		}
+		break;
+
+	default:
+		if (verbose) {
+			outstr(": not found\n", out);
+		}
+		return 127;
+	}
+
+out:
+	outc('\n', out);
+	return 0;
+}
+
+int
+commandcmd(argc, argv)
+	int argc;
+	char **argv;
+{
+	char *cmd;
+	int c;
+	enum {
+		VERIFY_BRIEF = 1,
+		VERIFY_VERBOSE = 2,
+	} verify = 0;
+	const char *path = NULL;
+
+	while ((c = nextopt("pvV")) != '\0')
+		if (c == 'V')
+			verify |= VERIFY_VERBOSE;
+		else if (c == 'v')
+			verify |= VERIFY_BRIEF;
+#ifdef DEBUG
+		else if (c != 'p')
+			abort();
+#endif
+		else
+			path = defpath;
+
+	cmd = *argptr;
+	if (verify && cmd)
+		return describe_command(out1, cmd, path, verify - VERIFY_BRIEF);
+
+	return 0;
+}
diff --git a/bin/dash/src/exec.h b/bin/dash/src/exec.h
new file mode 100644
index 00000000..423b07e6
--- /dev/null
+++ b/bin/dash/src/exec.h
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)exec.h	8.3 (Berkeley) 6/8/95
+ */
+
+/* values of cmdtype */
+#define CMDUNKNOWN	-1	/* no entry in table for command */
+#define CMDNORMAL	0	/* command is an executable program */
+#define CMDFUNCTION	1	/* command is a shell function */
+#define CMDBUILTIN	2	/* command is a shell builtin */
+
+
+struct cmdentry {
+	int cmdtype;
+	union param {
+		int index;
+		const struct builtincmd *cmd;
+		struct funcnode *func;
+	} u;
+};
+
+
+/* action to find_command() */
+#define DO_ERR		0x01	/* prints errors */
+#define DO_ABS		0x02	/* checks absolute paths */
+#define DO_NOFUNC	0x04	/* don't return shell functions, for command */
+#define DO_ALTPATH	0x08	/* using alternate path */
+#define DO_REGBLTIN	0x10	/* regular built-ins and functions only */
+
+union node;
+
+extern const char *pathopt;	/* set by padvance */
+
+void shellexec(char **, const char *, int)
+    __attribute__((__noreturn__));
+int padvance_magic(const char **path, const char *name, int magic);
+int hashcmd(int, char **);
+void find_command(char *, struct cmdentry *, int, const char *);
+struct builtincmd *find_builtin(const char *);
+void hashcd(void);
+void changepath(const char *);
+#ifdef notdef
+void getcmdentry(char *, struct cmdentry *);
+#endif
+void defun(union node *);
+void unsetfunc(const char *);
+int typecmd(int, char **);
+int commandcmd(int, char **);
+
+static inline int padvance(const char **path, const char *name)
+{
+	return padvance_magic(path, name, 1);
+}
diff --git a/bin/dash/src/expand.c b/bin/dash/src/expand.c
new file mode 100644
index 00000000..1730670e
--- /dev/null
+++ b/bin/dash/src/expand.c
@@ -0,0 +1,1753 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#ifdef HAVE_GETPWNAM
+#include <pwd.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+#ifdef HAVE_FNMATCH
+#include <fnmatch.h>
+#endif
+#ifdef HAVE_GLOB
+#include <glob.h>
+#endif
+#include <ctype.h>
+#include <stdbool.h>
+
+/*
+ * Routines to expand arguments to commands.  We have to deal with
+ * backquotes, shell variables, and file metacharacters.
+ */
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"
+#include "eval.h"
+#include "expand.h"
+#include "syntax.h"
+#include "parser.h"
+#include "jobs.h"
+#include "options.h"
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "show.h"
+#include "system.h"
+
+/*
+ * _rmescape() flags
+ */
+#define RMESCAPE_ALLOC	0x1	/* Allocate a new string */
+#define RMESCAPE_GLOB	0x2	/* Add backslashes for glob */
+#define RMESCAPE_GROW	0x8	/* Grow strings instead of stalloc */
+#define RMESCAPE_HEAP	0x10	/* Malloc strings instead of stalloc */
+
+/* Add CTLESC when necessary. */
+#define QUOTES_ESC	(EXP_FULL | EXP_CASE)
+
+/*
+ * Structure specifying which parts of the string should be searched
+ * for IFS characters.
+ */
+
+struct ifsregion {
+	struct ifsregion *next;	/* next region in list */
+	int begoff;		/* offset of start of region */
+	int endoff;		/* offset of end of region */
+	int nulonly;		/* search for nul bytes only */
+};
+
+/* output of current string */
+static char *expdest;
+/* list of back quote expressions */
+static struct nodelist *argbackq;
+/* first struct in list of ifs regions */
+static struct ifsregion ifsfirst;
+/* last struct in list */
+static struct ifsregion *ifslastp;
+/* holds expanded arg list */
+static struct arglist exparg;
+
+static char *argstr(char *p, int flag);
+static char *exptilde(char *startp, int flag);
+static char *expari(char *start, int flag);
+STATIC void expbackq(union node *, int);
+STATIC char *evalvar(char *, int);
+static size_t strtodest(const char *p, int flags);
+static size_t memtodest(const char *p, size_t len, int flags);
+STATIC ssize_t varvalue(char *, int, int, int);
+STATIC void expandmeta(struct strlist *);
+#ifdef HAVE_GLOB
+STATIC void addglob(const glob_t *);
+#else
+STATIC void expmeta(char *, unsigned, unsigned);
+STATIC struct strlist *expsort(struct strlist *);
+STATIC struct strlist *msort(struct strlist *, int);
+#endif
+STATIC void addfname(char *);
+STATIC int patmatch(char *, const char *);
+#ifndef HAVE_FNMATCH
+STATIC int pmatch(const char *, const char *);
+#else
+#define pmatch(a, b) !fnmatch((a), (b), 0)
+#endif
+static size_t cvtnum(intmax_t num, int flags);
+STATIC size_t esclen(const char *, const char *);
+STATIC char *scanleft(char *, char *, char *, char *, int, int);
+STATIC char *scanright(char *, char *, char *, char *, int, int);
+STATIC void varunset(const char *, const char *, const char *, int)
+	__attribute__((__noreturn__));
+
+
+/*
+ * Prepare a pattern for a glob(3) call.
+ *
+ * Returns an stalloced string.
+ */
+
+STATIC inline char *
+preglob(const char *pattern, int flag) {
+	flag |= RMESCAPE_GLOB;
+	return _rmescapes((char *)pattern, flag);
+}
+
+
+STATIC size_t
+esclen(const char *start, const char *p) {
+	size_t esc = 0;
+
+	while (p > start && *--p == (char)CTLESC) {
+		esc++;
+	}
+	return esc;
+}
+
+
+static inline const char *getpwhome(const char *name)
+{
+#ifdef HAVE_GETPWNAM
+	struct passwd *pw = getpwnam(name);
+	return pw ? pw->pw_dir : 0;
+#else
+	return 0;
+#endif
+}
+
+
+/*
+ * Perform variable substitution and command substitution on an argument,
+ * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
+ * perform splitting and file name expansion.  When arglist is NULL, perform
+ * here document expansion.
+ */
+
+void
+expandarg(union node *arg, struct arglist *arglist, int flag)
+{
+	struct strlist *sp;
+	char *p;
+
+	argbackq = arg->narg.backquote;
+	STARTSTACKSTR(expdest);
+	argstr(arg->narg.text, flag);
+	if (arglist == NULL) {
+		/* here document expanded */
+		goto out;
+	}
+	p = grabstackstr(expdest);
+	exparg.lastp = &exparg.list;
+	/*
+	 * TODO - EXP_REDIR
+	 */
+	if (flag & EXP_FULL) {
+		ifsbreakup(p, -1, &exparg);
+		*exparg.lastp = NULL;
+		exparg.lastp = &exparg.list;
+		expandmeta(exparg.list);
+	} else {
+		sp = (struct strlist *)stalloc(sizeof (struct strlist));
+		sp->text = p;
+		*exparg.lastp = sp;
+		exparg.lastp = &sp->next;
+	}
+	*exparg.lastp = NULL;
+	if (exparg.list) {
+		*arglist->lastp = exparg.list;
+		arglist->lastp = exparg.lastp;
+	}
+
+out:
+	ifsfree();
+}
+
+
+
+/*
+ * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
+ * characters to allow for further processing.  Otherwise treat
+ * $@ like $* since no splitting will be performed.
+ */
+
+static char *argstr(char *p, int flag)
+{
+	static const char spclchars[] = {
+		'=',
+		':',
+		CTLQUOTEMARK,
+		CTLENDVAR,
+		CTLESC,
+		CTLVAR,
+		CTLBACKQ,
+		CTLARI,
+		CTLENDARI,
+		0
+	};
+	const char *reject = spclchars;
+	int c;
+	int breakall = (flag & (EXP_WORD | EXP_QUOTED)) == EXP_WORD;
+	int inquotes;
+	size_t length;
+	int startloc;
+
+	reject += !!(flag & EXP_VARTILDE2);
+	reject += flag & EXP_VARTILDE ? 0 : 2;
+	inquotes = 0;
+	length = 0;
+	if (flag & EXP_TILDE) {
+		flag &= ~EXP_TILDE;
+tilde:
+		if (*p == '~')
+			p = exptilde(p, flag);
+	}
+start:
+	startloc = expdest - (char *)stackblock();
+	for (;;) {
+		int end;
+
+		length += strcspn(p + length, reject);
+		end = 0;
+		c = (signed char)p[length];
+		if (!(c & 0x80) || c == CTLENDARI || c == CTLENDVAR) {
+			/*
+			 * c == '=' || c == ':' || c == '\0' ||
+			 * c == CTLENDARI || c == CTLENDVAR
+			 */
+			length++;
+			/* c == '\0' || c == CTLENDARI || c == CTLENDVAR */
+			end = !!((c - 1) & 0x80);
+		}
+		if (length > 0 && !(flag & EXP_DISCARD)) {
+			int newloc;
+			char *q;
+
+			q = stnputs(p, length, expdest);
+			q[-1] &= end - 1;
+			expdest = q - (flag & EXP_WORD ? end : 0);
+			newloc = q - (char *)stackblock() - end;
+			if (breakall && !inquotes && newloc > startloc) {
+				recordregion(startloc, newloc, 0);
+			}
+			startloc = newloc;
+		}
+		p += length + 1;
+		length = 0;
+
+		if (end)
+			break;
+
+		switch (c) {
+		case '=':
+			flag |= EXP_VARTILDE2;
+			reject++;
+			/* fall through */
+		case ':':
+			/*
+			 * sort of a hack - expand tildes in variable
+			 * assignments (after the first '=' and after ':'s).
+			 */
+			if (*--p == '~') {
+				goto tilde;
+			}
+			continue;
+		case CTLQUOTEMARK:
+			/* "$@" syntax adherence hack */
+			if (!inquotes && !memcmp(p, dolatstr + 1,
+						 DOLATSTRLEN - 1)) {
+				p = evalvar(p + 1, flag | EXP_QUOTED) + 1;
+				goto start;
+			}
+			inquotes ^= EXP_QUOTED;
+addquote:
+			if (flag & QUOTES_ESC) {
+				p--;
+				length++;
+				startloc++;
+			}
+			break;
+		case CTLESC:
+			startloc++;
+			length++;
+			goto addquote;
+		case CTLVAR:
+			p = evalvar(p, flag | inquotes);
+			goto start;
+		case CTLBACKQ:
+			expbackq(argbackq->n, flag | inquotes);
+			goto start;
+		case CTLARI:
+			p = expari(p, flag | inquotes);
+			goto start;
+		}
+	}
+	return p - 1;
+}
+
+static char *exptilde(char *startp, int flag)
+{
+	signed char c;
+	char *name;
+	const char *home;
+	char *p;
+
+	p = startp;
+	name = p + 1;
+
+	while ((c = *++p) != '\0') {
+		switch(c) {
+		case CTLESC:
+			return (startp);
+		case CTLQUOTEMARK:
+			return (startp);
+		case ':':
+			if (flag & EXP_VARTILDE)
+				goto done;
+			break;
+		case '/':
+		case CTLENDVAR:
+			goto done;
+		}
+	}
+done:
+	if (flag & EXP_DISCARD)
+		goto out;
+	*p = '\0';
+	if (*name == '\0') {
+		home = lookupvar(homestr);
+	} else {
+		home = getpwhome(name);
+	}
+	*p = c;
+	if (!home)
+		goto lose;
+	strtodest(home, flag | EXP_QUOTED);
+out:
+	return (p);
+lose:
+	return (startp);
+}
+
+
+void 
+removerecordregions(int endoff)
+{
+	if (ifslastp == NULL)
+		return;
+
+	if (ifsfirst.endoff > endoff) {
+		while (ifsfirst.next != NULL) {
+			struct ifsregion *ifsp;
+			INTOFF;
+			ifsp = ifsfirst.next->next;
+			ckfree(ifsfirst.next);
+			ifsfirst.next = ifsp;
+			INTON;
+		}
+		if (ifsfirst.begoff > endoff)
+			ifslastp = NULL;
+		else {
+			ifslastp = &ifsfirst;
+			ifsfirst.endoff = endoff;
+		}
+		return;
+	}
+	
+	ifslastp = &ifsfirst;
+	while (ifslastp->next && ifslastp->next->begoff < endoff)
+		ifslastp=ifslastp->next;
+	while (ifslastp->next != NULL) {
+		struct ifsregion *ifsp;
+		INTOFF;
+		ifsp = ifslastp->next->next;
+		ckfree(ifslastp->next);
+		ifslastp->next = ifsp;
+		INTON;
+	}
+	if (ifslastp->endoff > endoff)
+		ifslastp->endoff = endoff;
+}
+
+
+/*
+ * Expand arithmetic expression.  Backup to start of expression,
+ * evaluate, place result in (backed up) result, adjust string position.
+ */
+static char *expari(char *start, int flag)
+{
+	struct stackmark sm;
+	int begoff;
+	int endoff;
+	int len;
+	intmax_t result;
+	char *p;
+
+	p = stackblock();
+	begoff = expdest - p;
+	p = argstr(start, flag & EXP_DISCARD);
+
+	if (flag & EXP_DISCARD)
+		goto out;
+
+	start = stackblock();
+	endoff = expdest - start;
+	start += begoff;
+	STADJUST(start - expdest, expdest);
+
+	removerecordregions(begoff);
+
+	if (likely(flag & QUOTES_ESC))
+		rmescapes(start);
+
+	pushstackmark(&sm, endoff);
+	result = arith(start);
+	popstackmark(&sm);
+
+	len = cvtnum(result, flag);
+
+	if (likely(!(flag & EXP_QUOTED)))
+		recordregion(begoff, begoff + len, 0);
+
+out:
+	return p;
+}
+
+
+/*
+ * Expand stuff in backwards quotes.
+ */
+
+STATIC void
+expbackq(union node *cmd, int flag)
+{
+	struct backcmd in;
+	int i;
+	char buf[128];
+	char *p;
+	char *dest;
+	int startloc;
+	struct stackmark smark;
+
+	if (flag & EXP_DISCARD)
+		goto out;
+
+	INTOFF;
+	startloc = expdest - (char *)stackblock();
+	pushstackmark(&smark, startloc);
+	evalbackcmd(cmd, (struct backcmd *) &in);
+	popstackmark(&smark);
+
+	p = in.buf;
+	i = in.nleft;
+	if (i == 0)
+		goto read;
+	for (;;) {
+		memtodest(p, i, flag);
+read:
+		if (in.fd < 0)
+			break;
+		do {
+			i = read(in.fd, buf, sizeof buf);
+		} while (i < 0 && errno == EINTR);
+		TRACE(("expbackq: read returns %d\n", i));
+		if (i <= 0)
+			break;
+		p = buf;
+	}
+
+	if (in.buf)
+		ckfree(in.buf);
+	if (in.fd >= 0) {
+		close(in.fd);
+		back_exitstatus = waitforjob(in.jp);
+	}
+	INTON;
+
+	/* Eat all trailing newlines */
+	dest = expdest;
+	for (; dest > ((char *)stackblock() + startloc) && dest[-1] == '\n';)
+		STUNPUTC(dest);
+	expdest = dest;
+
+	if (!(flag & EXP_QUOTED))
+		recordregion(startloc, dest - (char *)stackblock(), 0);
+	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
+		(dest - (char *)stackblock()) - startloc,
+		(dest - (char *)stackblock()) - startloc,
+		stackblock() + startloc));
+
+out:
+	argbackq = argbackq->next;
+}
+
+
+STATIC char *
+scanleft(
+	char *startp, char *rmesc, char *rmescend, char *str, int quotes,
+	int zero
+) {
+	char *loc;
+	char *loc2;
+	char c;
+
+	loc = startp;
+	loc2 = rmesc;
+	do {
+		int match;
+		const char *s = loc2;
+		c = *loc2;
+		if (zero) {
+			*loc2 = '\0';
+			s = rmesc;
+		}
+		match = pmatch(str, s);
+		*loc2 = c;
+		if (match)
+			return loc;
+		if (quotes && *loc == (char)CTLESC)
+			loc++;
+		loc++;
+		loc2++;
+	} while (c);
+	return 0;
+}
+
+
+STATIC char *
+scanright(
+	char *startp, char *rmesc, char *rmescend, char *str, int quotes,
+	int zero
+) {
+	int esc = 0;
+	char *loc;
+	char *loc2;
+
+	for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
+		int match;
+		char c = *loc2;
+		const char *s = loc2;
+		if (zero) {
+			*loc2 = '\0';
+			s = rmesc;
+		}
+		match = pmatch(str, s);
+		*loc2 = c;
+		if (match)
+			return loc;
+		loc--;
+		if (quotes) {
+			if (--esc < 0) {
+				esc = esclen(startp, loc);
+			}
+			if (esc % 2) {
+				esc--;
+				loc--;
+			}
+		}
+	}
+	return 0;
+}
+
+static char *subevalvar(char *start, char *str, int strloc, int startloc,
+			int varflags, int flag)
+{
+	int subtype = varflags & VSTYPE;
+	int quotes = flag & QUOTES_ESC;
+	char *startp;
+	char *loc;
+	long amount;
+	char *rmesc, *rmescend;
+	int zero;
+	char *(*scan)(char *, char *, char *, char *, int , int);
+	char *p;
+
+	p = argstr(start, (flag & EXP_DISCARD) | EXP_TILDE |
+			  (str ?  0 : EXP_CASE));
+	if (flag & EXP_DISCARD)
+		return p;
+
+	startp = stackblock() + startloc;
+
+	switch (subtype) {
+	case VSASSIGN:
+		setvar(str, startp, 0);
+
+		loc = startp;
+		goto out;
+
+	case VSQUESTION:
+		varunset(start, str, startp, varflags);
+		/* NOTREACHED */
+	}
+
+	subtype -= VSTRIMRIGHT;
+#ifdef DEBUG
+	if (subtype < 0 || subtype > 3)
+		abort();
+#endif
+
+	rmesc = startp;
+	rmescend = stackblock() + strloc;
+	if (quotes) {
+		rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
+		if (rmesc != startp) {
+			rmescend = expdest;
+			startp = stackblock() + startloc;
+		}
+	}
+	rmescend--;
+	str = stackblock() + strloc;
+	preglob(str, 0);
+
+	/* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
+	zero = subtype >> 1;
+	/* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
+	scan = (subtype & 1) ^ zero ? scanleft : scanright;
+
+	loc = scan(startp, rmesc, rmescend, str, quotes, zero);
+	if (loc) {
+		if (zero) {
+			memmove(startp, loc, str - loc);
+			loc = startp + (str - loc) - 1;
+		}
+		*loc = '\0';
+	} else
+		loc = str - 1;
+
+out:
+	amount = loc - expdest;
+	STADJUST(amount, expdest);
+
+	/* Remove any recorded regions beyond start of variable */
+	removerecordregions(startloc);
+
+	return p;
+}
+
+
+/*
+ * Expand a variable, and return a pointer to the next character in the
+ * input string.
+ */
+STATIC char *
+evalvar(char *p, int flag)
+{
+	int subtype;
+	int varflags;
+	char *var;
+	int patloc;
+	int startloc;
+	ssize_t varlen;
+	int discard;
+	int quoted;
+
+	varflags = *p++;
+	subtype = varflags & VSTYPE;
+
+	quoted = flag & EXP_QUOTED;
+	var = p;
+	startloc = expdest - (char *)stackblock();
+	p = strchr(p, '=') + 1;
+
+again:
+	varlen = varvalue(var, varflags, flag, quoted);
+	if (varflags & VSNUL)
+		varlen--;
+
+	discard = varlen < 0 ? EXP_DISCARD : 0;
+
+	switch (subtype) {
+	case VSPLUS:
+		discard ^= EXP_DISCARD;
+		/* fall through */
+
+	case 0:
+	case VSMINUS:
+		p = argstr(p, flag | EXP_TILDE | EXP_WORD |
+			      (discard ^ EXP_DISCARD));
+		goto record;
+
+	case VSASSIGN:
+	case VSQUESTION:
+		p = subevalvar(p, var, 0, startloc, varflags,
+			       (flag & ~QUOTES_ESC) |
+			       (discard ^ EXP_DISCARD));
+
+		if ((flag | ~discard) & EXP_DISCARD)
+			goto record;
+
+		varflags &= ~VSNUL;
+		subtype = VSNORMAL;
+		goto again;
+	}
+
+	if ((discard & ~flag) && uflag)
+		varunset(p, var, 0, 0);
+
+	if (subtype == VSLENGTH) {
+		p++;
+		if (flag & EXP_DISCARD)
+			return p;
+		cvtnum(varlen > 0 ? varlen : 0, flag);
+		goto really_record;
+	}
+
+	if (subtype == VSNORMAL)
+		goto record;
+
+#ifdef DEBUG
+	switch (subtype) {
+	case VSTRIMLEFT:
+	case VSTRIMLEFTMAX:
+	case VSTRIMRIGHT:
+	case VSTRIMRIGHTMAX:
+		break;
+	default:
+		abort();
+	}
+#endif
+
+	flag |= discard;
+	if (!(flag & EXP_DISCARD)) {
+		/*
+		 * Terminate the string and start recording the pattern
+		 * right after it
+		 */
+		STPUTC('\0', expdest);
+	}
+
+	patloc = expdest - (char *)stackblock();
+	p = subevalvar(p, NULL, patloc, startloc, varflags, flag);
+
+record:
+	if ((flag | discard) & EXP_DISCARD)
+		return p;
+
+really_record:
+	if (quoted) {
+		quoted = *var == '@' && shellparam.nparam;
+		if (!quoted)
+			return p;
+	}
+	recordregion(startloc, expdest - (char *)stackblock(), quoted);
+	return p;
+}
+
+
+/*
+ * Put a string on the stack.
+ */
+
+static size_t memtodest(const char *p, size_t len, int flags)
+{
+	const char *syntax = flags & EXP_QUOTED ? DQSYNTAX : BASESYNTAX;
+	char *q;
+	char *s;
+
+	if (unlikely(!len))
+		return 0;
+
+	q = makestrspace(len * 2, expdest);
+	s = q;
+
+	do {
+		int c = (signed char)*p++;
+		if (c) {
+			if ((flags & QUOTES_ESC) &&
+			    ((syntax[c] == CCTL) ||
+			     (flags & EXP_QUOTED && syntax[c] == CBACK)))
+				USTPUTC(CTLESC, q);
+		} else if (!(flags & EXP_KEEPNUL))
+			continue;
+		USTPUTC(c, q);
+	} while (--len);
+
+	expdest = q;
+	return q - s;
+}
+
+
+static size_t strtodest(const char *p, int flags)
+{
+	size_t len = strlen(p);
+	memtodest(p, len, flags);
+	return len;
+}
+
+
+
+/*
+ * Add the value of a specialized variable to the stack string.
+ */
+
+STATIC ssize_t
+varvalue(char *name, int varflags, int flags, int quoted)
+{
+	int num;
+	char *p;
+	int i;
+	int sep;
+	char sepc;
+	char **ap;
+	int subtype = varflags & VSTYPE;
+	int discard = (subtype == VSPLUS || subtype == VSLENGTH) |
+		      (flags & EXP_DISCARD);
+	ssize_t len = 0;
+	char c;
+
+	if (!subtype) {
+		if (discard)
+			return -1;
+
+		sh_error("Bad substitution");
+	}
+
+	flags |= EXP_KEEPNUL;
+	flags &= discard ? ~QUOTES_ESC : ~0;
+	sep = (flags & EXP_FULL) << CHAR_BIT;
+
+	switch (*name) {
+	case '$':
+		num = rootpid;
+		goto numvar;
+	case '?':
+		num = exitstatus;
+		goto numvar;
+	case '#':
+		num = shellparam.nparam;
+		goto numvar;
+	case '!':
+		num = backgndpid;
+		if (num == 0)
+			return -1;
+numvar:
+		len = cvtnum(num, flags);
+		break;
+	case '-':
+		p = makestrspace(NOPTS, expdest);
+		for (i = NOPTS - 1; i >= 0; i--) {
+			if (optlist[i] && optletters[i]) {
+				USTPUTC(optletters[i], p);
+				len++;
+			}
+		}
+		expdest = p;
+		break;
+	case '@':
+		if (quoted && sep)
+			goto param;
+		/* fall through */
+	case '*':
+		/* We will set c to 0 or ~0 depending on whether
+		 * we're doing field splitting.  We won't do field
+		 * splitting if either we're quoted or sep is zero.
+		 *
+		 * Instead of testing (quoted || !sep) the following
+		 * trick optimises away any branches by using the
+		 * fact that EXP_QUOTED (which is the only bit that
+		 * can be set in quoted) is the same as EXP_FULL <<
+		 * CHAR_BIT (which is the only bit that can be set
+		 * in sep).
+		 */
+#if EXP_QUOTED >> CHAR_BIT != EXP_FULL
+#error The following two lines expect EXP_QUOTED == EXP_FULL << CHAR_BIT
+#endif
+		c = !((quoted | ~sep) & EXP_QUOTED) - 1;
+		sep &= ~quoted;
+		sep |= ifsset() ? (unsigned char)(c & ifsval()[0]) : ' ';
+param:
+		sepc = sep;
+		if (!(ap = shellparam.p))
+			return -1;
+		while ((p = *ap++)) {
+			len += strtodest(p, flags);
+
+			if (*ap && sep) {
+				len++;
+				memtodest(&sepc, 1, flags);
+			}
+		}
+		break;
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+		num = atoi(name);
+		if (num < 0 || num > shellparam.nparam)
+			return -1;
+		p = num ? shellparam.p[num - 1] : arg0;
+		goto value;
+	default:
+		p = lookupvar(name);
+value:
+		if (!p)
+			return -1;
+
+		len = strtodest(p, flags);
+		break;
+	}
+
+	if (discard)
+		STADJUST(-len, expdest);
+
+	return len;
+}
+
+
+
+/*
+ * Record the fact that we have to scan this region of the
+ * string for IFS characters.
+ */
+
+void
+recordregion(int start, int end, int nulonly)
+{
+	struct ifsregion *ifsp;
+
+	if (ifslastp == NULL) {
+		ifsp = &ifsfirst;
+	} else {
+		INTOFF;
+		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
+		ifsp->next = NULL;
+		ifslastp->next = ifsp;
+		INTON;
+	}
+	ifslastp = ifsp;
+	ifslastp->begoff = start;
+	ifslastp->endoff = end;
+	ifslastp->nulonly = nulonly;
+}
+
+
+
+/*
+ * Break the argument string into pieces based upon IFS and add the
+ * strings to the argument list.  The regions of the string to be
+ * searched for IFS characters have been stored by recordregion.
+ * If maxargs is non-negative, at most maxargs arguments will be created, by
+ * joining together the last arguments.
+ */
+void
+ifsbreakup(char *string, int maxargs, struct arglist *arglist)
+{
+	struct ifsregion *ifsp;
+	struct strlist *sp;
+	char *start;
+	char *p;
+	char *q;
+	char *r = NULL;
+	const char *ifs, *realifs;
+	int ifsspc;
+	int nulonly;
+
+
+	start = string;
+	if (ifslastp != NULL) {
+		ifsspc = 0;
+		nulonly = 0;
+		realifs = ifsset() ? ifsval() : defifs;
+		ifsp = &ifsfirst;
+		do {
+			int afternul;
+
+			p = string + ifsp->begoff;
+			afternul = nulonly;
+			nulonly = ifsp->nulonly;
+			ifs = nulonly ? nullstr : realifs;
+			ifsspc = 0;
+			while (p < string + ifsp->endoff) {
+				int c;
+				bool isifs;
+				bool isdefifs;
+
+				q = p;
+				c = *p++;
+				if (c == (char)CTLESC)
+					c = *p++;
+
+				isifs = strchr(ifs, c);
+				isdefifs = false;
+				if (isifs)
+					isdefifs = strchr(defifs, c);
+
+				/* If only reading one more argument:
+				 * If we have exactly one field,
+				 * read that field without its terminator.
+				 * If we have more than one field,
+				 * read all fields including their terminators,
+				 * except for trailing IFS whitespace.
+				 *
+				 * This means that if we have only IFS
+				 * characters left, and at most one
+				 * of them is non-whitespace, we stop
+				 * reading here.
+				 * Otherwise, we read all the remaining
+				 * characters except for trailing
+				 * IFS whitespace.
+				 *
+				 * In any case, r indicates the start
+				 * of the characters to remove, or NULL
+				 * if no characters should be removed.
+				 */
+				if (!maxargs) {
+					if (isdefifs) {
+						if (!r)
+							r = q;
+						continue;
+					}
+
+					if (!(isifs && ifsspc))
+						r = NULL;
+
+					ifsspc = 0;
+					continue;
+				}
+
+				if (ifsspc) {
+					if (isifs)
+						q = p;
+
+					start = q;
+
+					if (isdefifs)
+						continue;
+
+					isifs = false;
+				}
+
+				if (isifs) {
+					if (!(afternul || nulonly))
+						ifsspc = isdefifs;
+					/* Ignore IFS whitespace at start */
+					if (q == start && ifsspc) {
+						start = p;
+						ifsspc = 0;
+						continue;
+					}
+					if (maxargs > 0 && !--maxargs) {
+						r = q;
+						continue;
+					}
+					*q = '\0';
+					sp = (struct strlist *)stalloc(sizeof *sp);
+					sp->text = start;
+					*arglist->lastp = sp;
+					arglist->lastp = &sp->next;
+					start = p;
+					continue;
+				}
+
+				ifsspc = 0;
+			}
+		} while ((ifsp = ifsp->next) != NULL);
+		if (nulonly)
+			goto add;
+	}
+
+	if (r)
+		*r = '\0';
+
+	if (!*start)
+		return;
+
+add:
+	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp->text = start;
+	*arglist->lastp = sp;
+	arglist->lastp = &sp->next;
+}
+
+void ifsfree(void)
+{
+	struct ifsregion *p = ifsfirst.next;
+
+	if (!p)
+		goto out;
+
+	INTOFF;
+	do {
+		struct ifsregion *ifsp;
+		ifsp = p->next;
+		ckfree(p);
+		p = ifsp;
+	} while (p);
+	ifsfirst.next = NULL;
+	INTON;
+
+out:
+	ifslastp = NULL;
+}
+
+
+
+/*
+ * Expand shell metacharacters.  At this point, the only control characters
+ * should be escapes.  The results are stored in the list exparg.
+ */
+
+#ifdef HAVE_GLOB
+STATIC void
+expandmeta(struct strlist *str)
+{
+	/* TODO - EXP_REDIR */
+
+	while (str) {
+		const char *p;
+		glob_t pglob;
+		int i;
+
+		if (fflag)
+			goto nometa;
+		INTOFF;
+		p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
+		i = glob(p, GLOB_NOMAGIC, 0, &pglob);
+		if (p != str->text)
+			ckfree(p);
+		switch (i) {
+		case 0:
+			if ((pglob.gl_flags & (GLOB_NOMAGIC | GLOB_NOCHECK)) ==
+			    (GLOB_NOMAGIC | GLOB_NOCHECK))
+				goto nometa2;
+			addglob(&pglob);
+			globfree(&pglob);
+			INTON;
+			break;
+		case GLOB_NOMATCH:
+nometa2:
+			globfree(&pglob);
+			INTON;
+nometa:
+			*exparg.lastp = str;
+			rmescapes(str->text);
+			exparg.lastp = &str->next;
+			break;
+		default:	/* GLOB_NOSPACE */
+			sh_error("Out of space");
+		}
+		str = str->next;
+	}
+}
+
+
+/*
+ * Add the result of glob(3) to the list.
+ */
+
+STATIC void
+addglob(pglob)
+	const glob_t *pglob;
+{
+	char **p = pglob->gl_pathv;
+
+	do {
+		addfname(*p);
+	} while (*++p);
+}
+
+
+#else	/* HAVE_GLOB */
+STATIC char *expdir;
+STATIC unsigned expdir_max;
+
+
+STATIC void
+expandmeta(struct strlist *str)
+{
+	static const char metachars[] = {
+		'*', '?', '[', 0
+	};
+	/* TODO - EXP_REDIR */
+
+	while (str) {
+		struct strlist **savelastp;
+		struct strlist *sp;
+		char *p;
+		unsigned len;
+
+		if (fflag)
+			goto nometa;
+		if (!strpbrk(str->text, metachars))
+			goto nometa;
+		savelastp = exparg.lastp;
+
+		INTOFF;
+		p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
+		len = strlen(p);
+		expdir_max = len + PATH_MAX;
+		expdir = ckmalloc(expdir_max);
+
+		expmeta(p, len, 0);
+		ckfree(expdir);
+		if (p != str->text)
+			ckfree(p);
+		INTON;
+		if (exparg.lastp == savelastp) {
+			/*
+			 * no matches
+			 */
+nometa:
+			*exparg.lastp = str;
+			rmescapes(str->text);
+			exparg.lastp = &str->next;
+		} else {
+			*exparg.lastp = NULL;
+			*savelastp = sp = expsort(*savelastp);
+			while (sp->next != NULL)
+				sp = sp->next;
+			exparg.lastp = &sp->next;
+		}
+		str = str->next;
+	}
+}
+
+
+/*
+ * Do metacharacter (i.e. *, ?, [...]) expansion.
+ */
+
+STATIC void
+expmeta(char *name, unsigned name_len, unsigned expdir_len)
+{
+	char *enddir = expdir + expdir_len;
+	char *p;
+	const char *cp;
+	char *start;
+	char *endname;
+	int metaflag;
+	struct stat64 statb;
+	DIR *dirp;
+	struct dirent64 *dp;
+	int atend;
+	int matchdot;
+	int esc;
+
+	metaflag = 0;
+	start = name;
+	for (p = name; esc = 0, *p; p += esc + 1) {
+		if (*p == '*' || *p == '?')
+			metaflag = 1;
+		else if (*p == '[') {
+			char *q = p + 1;
+			if (*q == '!')
+				q++;
+			for (;;) {
+				if (*q == '\\')
+					q++;
+				if (*q == '/' || *q == '\0')
+					break;
+				if (*++q == ']') {
+					metaflag = 1;
+					break;
+				}
+			}
+		} else {
+			if (*p == '\\' && p[1])
+				esc++;
+			if (p[esc] == '/') {
+				if (metaflag)
+					break;
+				start = p + esc + 1;
+			}
+		}
+	}
+	if (metaflag == 0) {	/* we've reached the end of the file name */
+		if (!expdir_len)
+			return;
+		p = name;
+		do {
+			if (*p == '\\' && p[1])
+				p++;
+			*enddir++ = *p;
+		} while (*p++);
+		if (lstat64(expdir, &statb) >= 0)
+			addfname(expdir);
+		return;
+	}
+	endname = p;
+	if (name < start) {
+		p = name;
+		do {
+			if (*p == '\\' && p[1])
+				p++;
+			*enddir++ = *p++;
+		} while (p < start);
+	}
+	*enddir = 0;
+	cp = expdir;
+	expdir_len = enddir - cp;
+	if (!expdir_len)
+		cp = ".";
+	if ((dirp = opendir(cp)) == NULL)
+		return;
+	if (*endname == 0) {
+		atend = 1;
+	} else {
+		atend = 0;
+		*endname = '\0';
+		endname += esc + 1;
+	}
+	name_len -= endname - name;
+	matchdot = 0;
+	p = start;
+	if (*p == '\\')
+		p++;
+	if (*p == '.')
+		matchdot++;
+	while (! int_pending() && (dp = readdir64(dirp)) != NULL) {
+		if (dp->d_name[0] == '.' && ! matchdot)
+			continue;
+		if (pmatch(start, dp->d_name)) {
+			if (atend) {
+				scopy(dp->d_name, enddir);
+				addfname(expdir);
+			} else {
+				unsigned offset;
+				unsigned len;
+
+				p = stpcpy(enddir, dp->d_name);
+				*p = '/';
+
+				offset = p - expdir + 1;
+				len = offset + name_len + NAME_MAX;
+				if (len > expdir_max) {
+					len += PATH_MAX;
+					expdir = ckrealloc(expdir, len);
+					expdir_max = len;
+				}
+
+				expmeta(endname, name_len, offset);
+				enddir = expdir + expdir_len;
+			}
+		}
+	}
+	closedir(dirp);
+	if (! atend)
+		endname[-esc - 1] = esc ? '\\' : '/';
+}
+#endif	/* HAVE_GLOB */
+
+
+/*
+ * Add a file name to the list.
+ */
+
+STATIC void
+addfname(char *name)
+{
+	struct strlist *sp;
+
+	sp = (struct strlist *)stalloc(sizeof *sp);
+	sp->text = sstrdup(name);
+	*exparg.lastp = sp;
+	exparg.lastp = &sp->next;
+}
+
+
+#ifndef HAVE_GLOB
+/*
+ * Sort the results of file name expansion.  It calculates the number of
+ * strings to sort and then calls msort (short for merge sort) to do the
+ * work.
+ */
+
+STATIC struct strlist *
+expsort(struct strlist *str)
+{
+	int len;
+	struct strlist *sp;
+
+	len = 0;
+	for (sp = str ; sp ; sp = sp->next)
+		len++;
+	return msort(str, len);
+}
+
+
+STATIC struct strlist *
+msort(struct strlist *list, int len)
+{
+	struct strlist *p, *q = NULL;
+	struct strlist **lpp;
+	int half;
+	int n;
+
+	if (len <= 1)
+		return list;
+	half = len >> 1;
+	p = list;
+	for (n = half ; --n >= 0 ; ) {
+		q = p;
+		p = p->next;
+	}
+	q->next = NULL;			/* terminate first half of list */
+	q = msort(list, half);		/* sort first half of list */
+	p = msort(p, len - half);		/* sort second half */
+	lpp = &list;
+	for (;;) {
+		if (strcmp(p->text, q->text) < 0) {
+			*lpp = p;
+			lpp = &p->next;
+			if ((p = *lpp) == NULL) {
+				*lpp = q;
+				break;
+			}
+		} else {
+			*lpp = q;
+			lpp = &q->next;
+			if ((q = *lpp) == NULL) {
+				*lpp = p;
+				break;
+			}
+		}
+	}
+	return list;
+}
+#endif
+
+
+/*
+ * Returns true if the pattern matches the string.
+ */
+
+STATIC inline int
+patmatch(char *pattern, const char *string)
+{
+	return pmatch(preglob(pattern, 0), string);
+}
+
+
+#ifndef HAVE_FNMATCH
+STATIC int ccmatch(const char *p, int chr, const char **r)
+{
+	static const struct class {
+		char name[10];
+		int (*fn)(int);
+	} classes[] = {
+		{ .name = ":alnum:]", .fn = isalnum },
+		{ .name = ":cntrl:]", .fn = iscntrl },
+		{ .name = ":lower:]", .fn = islower },
+		{ .name = ":space:]", .fn = isspace },
+		{ .name = ":alpha:]", .fn = isalpha },
+		{ .name = ":digit:]", .fn = isdigit },
+		{ .name = ":print:]", .fn = isprint },
+		{ .name = ":upper:]", .fn = isupper },
+		{ .name = ":blank:]", .fn = isblank },
+		{ .name = ":graph:]", .fn = isgraph },
+		{ .name = ":punct:]", .fn = ispunct },
+		{ .name = ":xdigit:]", .fn = isxdigit },
+	};
+	const struct class *class, *end;
+
+	end = classes + sizeof(classes) / sizeof(classes[0]);
+	for (class = classes; class < end; class++) {
+		const char *q;
+
+		q = prefix(p, class->name);
+		if (!q)
+			continue;
+		*r = q;
+		return class->fn(chr);
+	}
+
+	*r = 0;
+	return 0;
+}
+
+STATIC int
+pmatch(const char *pattern, const char *string)
+{
+	const char *p, *q;
+	char c;
+
+	p = pattern;
+	q = string;
+	for (;;) {
+		switch (c = *p++) {
+		case '\0':
+			goto breakloop;
+		case '\\':
+			if (*p) {
+				c = *p++;
+			}
+			goto dft;
+		case '?':
+			if (*q++ == '\0')
+				return 0;
+			break;
+		case '*':
+			c = *p;
+			while (c == '*')
+				c = *++p;
+			if (c != '\\' && c != '?' && c != '*' && c != '[') {
+				while (*q != c) {
+					if (*q == '\0')
+						return 0;
+					q++;
+				}
+			}
+			do {
+				if (pmatch(p, q))
+					return 1;
+			} while (*q++ != '\0');
+			return 0;
+		case '[': {
+			const char *startp;
+			int invert, found;
+			char chr;
+
+			startp = p;
+			invert = 0;
+			if (*p == '!') {
+				invert++;
+				p++;
+			}
+			found = 0;
+			chr = *q;
+			if (chr == '\0')
+				return 0;
+			c = *p++;
+			do {
+				if (!c) {
+					p = startp;
+					c = '[';
+					goto dft;
+				}
+				if (c == '[') {
+					const char *r;
+
+					found |= !!ccmatch(p, chr, &r);
+					if (r) {
+						p = r;
+						continue;
+					}
+				} else if (c == '\\')
+					c = *p++;
+				if (*p == '-' && p[1] != ']') {
+					p++;
+					if (*p == '\\')
+						p++;
+					if (chr >= c && chr <= *p)
+						found = 1;
+					p++;
+				} else {
+					if (chr == c)
+						found = 1;
+				}
+			} while ((c = *p++) != ']');
+			if (found == invert)
+				return 0;
+			q++;
+			break;
+		}
+dft:	        default:
+			if (*q++ != c)
+				return 0;
+			break;
+		}
+	}
+breakloop:
+	if (*q != '\0')
+		return 0;
+	return 1;
+}
+#endif
+
+
+
+/*
+ * Remove any CTLESC characters from a string.
+ */
+
+char *
+_rmescapes(char *str, int flag)
+{
+	char *p, *q, *r;
+	int notescaped;
+	int globbing;
+
+	p = strpbrk(str, qchars);
+	if (!p) {
+		return str;
+	}
+	q = p;
+	r = str;
+	if (flag & RMESCAPE_ALLOC) {
+		size_t len = p - str;
+		size_t fulllen = len + strlen(p) + 1;
+
+		if (flag & RMESCAPE_GROW) {
+			int strloc = str - (char *)stackblock();
+
+			r = makestrspace(fulllen, expdest);
+			str = (char *)stackblock() + strloc;
+			p = str + len;
+		} else if (flag & RMESCAPE_HEAP) {
+			r = ckmalloc(fulllen);
+		} else {
+			r = stalloc(fulllen);
+		}
+		q = r;
+		if (len > 0) {
+			q = mempcpy(q, str, len);
+		}
+	}
+	globbing = flag & RMESCAPE_GLOB;
+	notescaped = globbing;
+	while (*p) {
+		if (*p == (char)CTLQUOTEMARK) {
+			p++;
+			notescaped = globbing;
+			continue;
+		}
+		if (*p == '\\') {
+			/* naked back slash */
+			notescaped = 0;
+			goto copy;
+		}
+		if (*p == (char)CTLESC) {
+			p++;
+			if (notescaped)
+				*q++ = '\\';
+		}
+		notescaped = globbing;
+copy:
+		*q++ = *p++;
+	}
+	*q = '\0';
+	if (flag & RMESCAPE_GROW) {
+		expdest = r;
+		STADJUST(q - r + 1, expdest);
+	}
+	return r;
+}
+
+
+
+/*
+ * See if a pattern matches in a case statement.
+ */
+
+int
+casematch(union node *pattern, char *val)
+{
+	struct stackmark smark;
+	int result;
+
+	setstackmark(&smark);
+	argbackq = pattern->narg.backquote;
+	STARTSTACKSTR(expdest);
+	argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
+	ifsfree();
+	result = patmatch(stackblock(), val);
+	popstackmark(&smark);
+	return result;
+}
+
+/*
+ * Our own itoa().
+ */
+
+static size_t cvtnum(intmax_t num, int flags)
+{
+	int len = max_int_length(sizeof(num));
+	char buf[len];
+
+	len = fmtstr(buf, len, "%" PRIdMAX, num);
+	return memtodest(buf, len, flags);
+}
+
+STATIC void
+varunset(const char *end, const char *var, const char *umsg, int varflags)
+{
+	const char *msg;
+	const char *tail;
+
+	tail = nullstr;
+	msg = "parameter not set";
+	if (umsg) {
+		if (*end == (char)CTLENDVAR) {
+			if (varflags & VSNUL)
+				tail = " or null";
+		} else
+			msg = umsg;
+	}
+	sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
+}
+
+#ifdef mkinit
+
+INCLUDE "expand.h"
+
+EXITRESET {
+	ifsfree();
+}
+
+#endif
diff --git a/bin/dash/src/expand.h b/bin/dash/src/expand.h
new file mode 100644
index 00000000..c44b8481
--- /dev/null
+++ b/bin/dash/src/expand.h
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)expand.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <inttypes.h>
+
+struct strlist {
+	struct strlist *next;
+	char *text;
+};
+
+
+struct arglist {
+	struct strlist *list;
+	struct strlist **lastp;
+};
+
+/*
+ * expandarg() flags
+ */
+#define EXP_FULL	0x1	/* perform word splitting & file globbing */
+#define EXP_TILDE	0x2	/* do normal tilde expansion */
+#define	EXP_VARTILDE	0x4	/* expand tildes in an assignment */
+#define	EXP_REDIR	0x8	/* file glob for a redirection (1 match only) */
+#define EXP_CASE	0x10	/* keeps quotes around for CASE pattern */
+#define EXP_VARTILDE2	0x40	/* expand tildes after colons only */
+#define EXP_WORD	0x80	/* expand word in parameter expansion */
+#define EXP_QUOTED	0x100	/* expand word in double quotes */
+#define EXP_KEEPNUL	0x200	/* do not skip NUL characters */
+#define EXP_DISCARD	0x400	/* discard result of expansion */
+
+
+union node;
+void expandarg(union node *, struct arglist *, int);
+#define rmescapes(p) _rmescapes((p), 0)
+char *_rmescapes(char *, int);
+int casematch(union node *, char *);
+void recordregion(int, int, int);
+void removerecordregions(int); 
+void ifsbreakup(char *, int, struct arglist *);
+void ifsfree(void);
+
+/* From arith.y */
+intmax_t arith(const char *);
+int expcmd(int , char **);
+#ifdef USE_LEX
+void arith_lex_reset(void);
+#else
+#define arith_lex_reset()
+#endif
+int yylex(void);
diff --git a/bin/dash/src/funcs/cmv b/bin/dash/src/funcs/cmv
new file mode 100644
index 00000000..91a67c53
--- /dev/null
+++ b/bin/dash/src/funcs/cmv
@@ -0,0 +1,47 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)cmv	8.2 (Berkeley) 5/4/95
+
+# Conditional move--don't replace an existing file.
+
+cmv() {
+	if test $# != 2
+	then	echo "cmv: arg count"
+		return 2
+	fi
+	if test -f "$2" -o -w "$2"
+	then	echo "$2 exists"
+		return 2
+	fi
+	/bin/mv "$1" "$2"
+}
diff --git a/bin/dash/src/funcs/dirs b/bin/dash/src/funcs/dirs
new file mode 100644
index 00000000..5f6ce635
--- /dev/null
+++ b/bin/dash/src/funcs/dirs
@@ -0,0 +1,71 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)dirs	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
diff --git a/bin/dash/src/funcs/kill b/bin/dash/src/funcs/kill
new file mode 100644
index 00000000..c5df95f5
--- /dev/null
+++ b/bin/dash/src/funcs/kill
@@ -0,0 +1,47 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)kill	8.2 (Berkeley) 5/4/95
+
+# Convert job names to process ids and then run /bin/kill.
+
+kill() {
+	local args x
+	args=
+	for x in "$@"
+	do	case $x in
+		%*)	x=`jobid "$x"` ;;
+		esac
+		args="$args $x"
+	done
+	/bin/kill $args
+}
diff --git a/bin/dash/src/funcs/login b/bin/dash/src/funcs/login
new file mode 100644
index 00000000..215e5352
--- /dev/null
+++ b/bin/dash/src/funcs/login
@@ -0,0 +1,36 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)login	8.2 (Berkeley) 5/4/95
+
+# replaces the login builtin in the BSD shell
+login () exec login "$@"
diff --git a/bin/dash/src/funcs/newgrp b/bin/dash/src/funcs/newgrp
new file mode 100644
index 00000000..ec0e7e5a
--- /dev/null
+++ b/bin/dash/src/funcs/newgrp
@@ -0,0 +1,35 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)newgrp	8.2 (Berkeley) 5/4/95
+
+newgrp() exec newgrp "$@"
diff --git a/bin/dash/src/funcs/popd b/bin/dash/src/funcs/popd
new file mode 100644
index 00000000..7bccf50d
--- /dev/null
+++ b/bin/dash/src/funcs/popd
@@ -0,0 +1,71 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)popd	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
diff --git a/bin/dash/src/funcs/pushd b/bin/dash/src/funcs/pushd
new file mode 100644
index 00000000..19ac8e08
--- /dev/null
+++ b/bin/dash/src/funcs/pushd
@@ -0,0 +1,71 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)pushd	8.2 (Berkeley) 5/4/95
+
+# pushd, popd, and dirs --- written by Chris Bertin
+# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris
+# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW
+
+pushd () {
+	SAVE=`pwd`
+	if [ "$1" = "" ] 
+	then	if [ "$DSTACK" = "" ]
+		then	echo "pushd: directory stack empty."
+			return 1
+		fi
+		set $DSTACK
+		cd $1 || return
+		shift 1
+		DSTACK="$*"
+	else	cd $1 > /dev/null || return
+	fi
+	DSTACK="$SAVE $DSTACK"
+	dirs
+}
+
+popd () {
+	if [ "$DSTACK" = "" ] 
+	then	echo "popd: directory stack empty."
+		return 1
+	fi
+	set $DSTACK
+	cd $1
+	shift
+	DSTACK=$*
+	dirs
+}
+
+dirs () {
+	echo "`pwd` $DSTACK"
+	return 0
+}
diff --git a/bin/dash/src/funcs/suspend b/bin/dash/src/funcs/suspend
new file mode 100644
index 00000000..44844678
--- /dev/null
+++ b/bin/dash/src/funcs/suspend
@@ -0,0 +1,39 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)suspend	8.2 (Berkeley) 5/4/95
+
+suspend() {
+	local -
+	set +j
+	kill -TSTP 0
+}
diff --git a/bin/dash/src/histedit.c b/bin/dash/src/histedit.c
new file mode 100644
index 00000000..1b7ad238
--- /dev/null
+++ b/bin/dash/src/histedit.c
@@ -0,0 +1,504 @@
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <sys/param.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+/*
+ * Editline and history functions (and glue).
+ */
+#include "shell.h"
+#include "parser.h"
+#include "var.h"
+#include "options.h"
+#include "main.h"
+#include "output.h"
+#include "mystring.h"
+#include "error.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#include "eval.h"
+#include "memalloc.h"
+
+#define MAXHISTLOOPS	4	/* max recursions through fc */
+#define DEFEDITOR	"ed"	/* default editor *should* be $EDITOR */
+
+History *hist;	/* history cookie */
+EditLine *el;	/* editline cookie */
+int displayhist;
+static FILE *el_in, *el_out;
+
+STATIC const char *fc_replace(const char *, char *, char *);
+
+#ifdef DEBUG
+extern FILE *tracefile;
+#endif
+
+/*
+ * Set history and editing status.  Called whenever the status may
+ * have changed (figures out what to do).
+ */
+void
+histedit(void)
+{
+	FILE *el_err;
+
+#define editing (Eflag || Vflag)
+
+	if (iflag) {
+		if (!hist) {
+			/*
+			 * turn history on
+			 */
+			INTOFF;
+			hist = history_init();
+			INTON;
+
+			if (hist != NULL)
+				sethistsize(histsizeval());
+			else
+				out2str("sh: can't initialize history\n");
+		}
+		if (editing && !el && isatty(0)) { /* && isatty(2) ??? */
+			/*
+			 * turn editing on
+			 */
+			INTOFF;
+			if (el_in == NULL)
+				el_in = fdopen(0, "r");
+			if (el_out == NULL)
+				el_out = fdopen(2, "w");
+			if (el_in == NULL || el_out == NULL)
+				goto bad;
+			el_err = el_out;
+#if DEBUG
+			if (tracefile)
+				el_err = tracefile;
+#endif
+			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_RPROMPT, getrprompt);
+#ifdef HAVE__EL_FN_SH_COMPLETE
+				el_set(el, EL_ADDFN, "sh-complete", "Filename completion",
+					_el_fn_sh_complete);
+#else
+				el_set(el, EL_ADDFN, "sh-complete", "Filename completion",
+					_el_fn_complete);
+#endif
+			} else {
+bad:
+				out2str("sh: can't initialize editing\n");
+			}
+			INTON;
+		} else if (!editing && el) {
+			INTOFF;
+			el_end(el);
+			el = NULL;
+			INTON;
+		}
+		if (el) {
+			if (Vflag)
+				el_set(el, EL_EDITOR, "vi");
+			else if (Eflag)
+				el_set(el, EL_EDITOR, "emacs");
+			el_source(el, NULL);
+			el_set(el, EL_BIND, "^I", "sh-complete", NULL);
+		}
+	} else {
+		INTOFF;
+		if (el) {	/* no editing if not interactive */
+			el_end(el);
+			el = NULL;
+		}
+		if (hist) {
+			history_end(hist);
+			hist = NULL;
+		}
+		INTON;
+	}
+}
+
+
+void
+sethistsize(const char *hs)
+{
+	int histsize;
+	HistEvent he;
+
+	if (hist != NULL) {
+		if (hs == NULL || *hs == '\0' ||
+		   (histsize = atoi(hs)) < 0)
+			histsize = 100;
+		history(hist, &he, H_SETSIZE, histsize);
+		history(hist, &he, H_SETUNIQUE, 1);
+	}
+}
+
+void
+setterm(const char *term)
+{
+	if (el != NULL && term != NULL)
+		if (el_set(el, EL_TERMINAL, term) != 0) {
+			outfmt(out2, "sh: Can't set terminal type %s\n", term);
+			outfmt(out2, "sh: Using dumb terminal settings.\n");
+		}
+}
+
+/*
+ *  This command is provided since POSIX decided to standardize
+ *  the Korn shell fc command.  Oh well...
+ */
+int
+histcmd(int argc, char **argv)
+{
+	int ch;
+	const char *editor = NULL;
+	HistEvent he;
+	int lflg = 0, nflg = 0, rflg = 0, sflg = 0;
+	int i, retval;
+	const char *firststr, *laststr;
+	int first, last, direction;
+	char *pat = NULL, *repl;	/* ksh "fc old=new" crap */
+	static int active = 0;
+	struct jmploc jmploc;
+	struct jmploc *volatile savehandler;
+	char editfile[MAXPATHLEN + 1];
+	FILE *efp;
+#ifdef __GNUC__
+	/* Avoid longjmp clobbering */
+	(void) &editor;
+	(void) &lflg;
+	(void) &nflg;
+	(void) &rflg;
+	(void) &sflg;
+	(void) &firststr;
+	(void) &laststr;
+	(void) &pat;
+	(void) &repl;
+	(void) &efp;
+	(void) &argc;
+	(void) &argv;
+#endif
+
+	if (hist == NULL)
+		sh_error("history not active");
+
+	if (argc == 1)
+		sh_error("missing history argument");
+
+#ifdef __GLIBC__
+	optind = 0;
+#else
+	optreset = 1; optind = 1; /* initialize getopt */
+#endif
+	while (not_fcnumber(argv[optind]) &&
+	      (ch = getopt(argc, argv, ":e:lnrs")) != -1)
+		switch ((char)ch) {
+		case 'e':
+			editor = optionarg;
+			break;
+		case 'l':
+			lflg = 1;
+			break;
+		case 'n':
+			nflg = 1;
+			break;
+		case 'r':
+			rflg = 1;
+			break;
+		case 's':
+			sflg = 1;
+			break;
+		case ':':
+			sh_error("option -%c expects argument", optopt);
+			/* NOTREACHED */
+		case '?':
+		default:
+			sh_error("unknown option: -%c", optopt);
+			/* NOTREACHED */
+		}
+	argc -= optind, argv += optind;
+
+	/*
+	 * If executing...
+	 */
+	if (lflg == 0 || editor || sflg) {
+		lflg = 0;	/* ignore */
+		editfile[0] = '\0';
+		/*
+		 * Catch interrupts to reset active counter and
+		 * cleanup temp files.
+		 */
+		if (setjmp(jmploc.loc)) {
+			active = 0;
+			if (*editfile)
+				unlink(editfile);
+			handler = savehandler;
+			longjmp(handler->loc, 1);
+		}
+		savehandler = handler;
+		handler = &jmploc;
+		if (++active > MAXHISTLOOPS) {
+			active = 0;
+			displayhist = 0;
+			sh_error("called recursively too many times");
+		}
+		/*
+		 * Set editor.
+		 */
+		if (sflg == 0) {
+			if (editor == NULL &&
+			    (editor = bltinlookup("FCEDIT")) == NULL &&
+			    (editor = bltinlookup("EDITOR")) == NULL)
+				editor = DEFEDITOR;
+			if (editor[0] == '-' && editor[1] == '\0') {
+				sflg = 1;	/* no edit */
+				editor = NULL;
+			}
+		}
+	}
+
+	/*
+	 * If executing, parse [old=new] now
+	 */
+	if (lflg == 0 && argc > 0 &&
+	     ((repl = strchr(argv[0], '=')) != NULL)) {
+		pat = argv[0];
+		*repl++ = '\0';
+		argc--, argv++;
+	}
+	/*
+	 * determine [first] and [last]
+	 */
+	switch (argc) {
+	case 0:
+		firststr = lflg ? "-16" : "-1";
+		laststr = "-1";
+		break;
+	case 1:
+		firststr = argv[0];
+		laststr = lflg ? "-1" : argv[0];
+		break;
+	case 2:
+		firststr = argv[0];
+		laststr = argv[1];
+		break;
+	default:
+		sh_error("too many args");
+		/* NOTREACHED */
+	}
+	/*
+	 * Turn into event numbers.
+	 */
+	first = str_to_event(firststr, 0);
+	last = str_to_event(laststr, 1);
+
+	if (rflg) {
+		i = last;
+		last = first;
+		first = i;
+	}
+	/*
+	 * XXX - this should not depend on the event numbers
+	 * always increasing.  Add sequence numbers or offset
+	 * to the history element in next (diskbased) release.
+	 */
+	direction = first < last ? H_PREV : H_NEXT;
+
+	/*
+	 * If editing, grab a temp file.
+	 */
+	if (editor) {
+		int fd;
+		INTOFF;		/* easier */
+		sprintf(editfile, "%s_shXXXXXX", _PATH_TMP);
+		if ((fd = mkstemp(editfile)) < 0)
+			sh_error("can't create temporary file %s", editfile);
+		if ((efp = fdopen(fd, "w")) == NULL) {
+			close(fd);
+			sh_error("can't allocate stdio buffer for temp");
+		}
+	}
+
+	/*
+	 * Loop through selected history events.  If listing or executing,
+	 * do it now.  Otherwise, put into temp file and call the editor
+	 * after.
+	 *
+	 * The history interface needs rethinking, as the following
+	 * convolutions will demonstrate.
+	 */
+	history(hist, &he, H_FIRST);
+	retval = history(hist, &he, H_NEXT_EVENT, first);
+	for (;retval != -1; retval = history(hist, &he, direction)) {
+		if (lflg) {
+			if (!nflg)
+				out1fmt("%5d ", he.num);
+			out1str(he.str);
+		} else {
+			const char *s = pat ?
+			   fc_replace(he.str, pat, repl) : he.str;
+
+			if (sflg) {
+				if (displayhist) {
+					out2str(s);
+				}
+
+				evalstring(s, 0);
+				if (displayhist && hist) {
+					/*
+					 *  XXX what about recursive and
+					 *  relative histnums.
+					 */
+					history(hist, &he, H_ENTER, s);
+				}
+			} else
+				fputs(s, efp);
+		}
+		/*
+		 * At end?  (if we were to lose last, we'd sure be
+		 * messed up).
+		 */
+		if (he.num == last)
+			break;
+	}
+	if (editor) {
+		char *editcmd;
+
+		fclose(efp);
+		editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
+		sprintf(editcmd, "%s %s", editor, editfile);
+		/* XXX - should use no JC command */
+		evalstring(editcmd, 0);
+		INTON;
+		readcmdfile(editfile);	/* XXX - should read back - quick tst */
+		unlink(editfile);
+	}
+
+	if (lflg == 0 && active > 0)
+		--active;
+	if (displayhist)
+		displayhist = 0;
+	return 0;
+}
+
+STATIC const char *
+fc_replace(const char *s, char *p, char *r)
+{
+	char *dest;
+	int plen = strlen(p);
+
+	STARTSTACKSTR(dest);
+	while (*s) {
+		if (*s == *p && strncmp(s, p, plen) == 0) {
+			while (*r)
+				STPUTC(*r++, dest);
+			s += plen;
+			*p = '\0';	/* so no more matches */
+		} else
+			STPUTC(*s++, dest);
+	}
+	STACKSTRNUL(dest);
+	dest = grabstackstr(dest);
+
+	return (dest);
+}
+
+int
+not_fcnumber(char *s)
+{
+	if (s == NULL)
+		return 0;
+        if (*s == '-')
+                s++;
+	return (!is_number(s));
+}
+
+int
+str_to_event(const char *str, int last)
+{
+	HistEvent he;
+	const char *s = str;
+	int relative = 0;
+	int i, retval;
+
+	retval = history(hist, &he, H_FIRST);
+	switch (*s) {
+	case '-':
+		relative = 1;
+		/*FALLTHROUGH*/
+	case '+':
+		s++;
+	}
+	if (is_number(s)) {
+		i = atoi(s);
+		if (relative) {
+			while (retval != -1 && i--) {
+				retval = history(hist, &he, H_NEXT);
+			}
+			if (retval == -1)
+				retval = history(hist, &he, H_LAST);
+		} else {
+			retval = history(hist, &he, H_NEXT_EVENT, i);
+			if (retval == -1) {
+				/*
+				 * the notion of first and last is
+				 * backwards to that of the history package
+				 */
+				retval = history(hist, &he,
+						last ? H_FIRST : H_LAST);
+			}
+		}
+		if (retval == -1)
+			sh_error("history number %s not found (internal error)",
+				 str);
+	} else {
+		/*
+		 * pattern
+		 */
+		retval = history(hist, &he, H_PREV_STR, str);
+		if (retval == -1)
+			sh_error("history pattern not found: %s", str);
+	}
+	return (he.num);
+}
+#endif
diff --git a/bin/dash/src/init.h b/bin/dash/src/init.h
new file mode 100644
index 00000000..d56fb28e
--- /dev/null
+++ b/bin/dash/src/init.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)init.h	8.2 (Berkeley) 5/4/95
+ */
+
+void init(void);
+void exitreset(void);
+void forkreset(void);
+void reset(void);
diff --git a/bin/dash/src/input.c b/bin/dash/src/input.c
new file mode 100644
index 00000000..4167bd18
--- /dev/null
+++ b/bin/dash/src/input.c
@@ -0,0 +1,498 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <stdio.h>	/* defines BUFSIZ */
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * This file implements the input routines used by the parser.
+ */
+
+#include "eval.h"
+#include "shell.h"
+#include "redir.h"
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "options.h"
+#include "memalloc.h"
+#include "error.h"
+#include "alias.h"
+#include "parser.h"
+#include "main.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+
+#define EOF_NLEFT -99		/* value of parsenleft when EOF pushed back */
+#define IBUFSIZ (BUFSIZ + 1)
+
+
+MKINIT struct parsefile basepf;	/* top level input file */
+MKINIT char basebuf[IBUFSIZ];	/* buffer for top level input file */
+struct parsefile *parsefile = &basepf;	/* current input file */
+int whichprompt;		/* 1 == PS1, 2 == PS2 */
+
+STATIC void pushfile(void);
+static int preadfd(void);
+static void setinputfd(int fd, int push);
+static int preadbuffer(void);
+
+#ifdef mkinit
+INCLUDE <stdio.h>
+INCLUDE <unistd.h>
+INCLUDE "input.h"
+INCLUDE "error.h"
+
+INIT {
+	basepf.nextc = basepf.buf = basebuf;
+	basepf.linno = 1;
+}
+
+RESET {
+	/* clear input buffer */
+	basepf.lleft = basepf.nleft = 0;
+	popallfiles();
+}
+
+FORKRESET {
+	popallfiles();
+	if (parsefile->fd > 0) {
+		close(parsefile->fd);
+		parsefile->fd = 0;
+	}
+}
+#endif
+
+
+/*
+ * Read a character from the script, returning PEOF on end of file.
+ * Nul characters in the input are silently discarded.
+ */
+
+int
+pgetc(void)
+{
+	int c;
+
+	if (parsefile->unget)
+		return parsefile->lastc[--parsefile->unget];
+
+	if (--parsefile->nleft >= 0)
+		c = (signed char)*parsefile->nextc++;
+	else
+		c = preadbuffer();
+
+	parsefile->lastc[1] = parsefile->lastc[0];
+	parsefile->lastc[0] = c;
+
+	return c;
+}
+
+
+/*
+ * Same as pgetc(), but ignores PEOA.
+ */
+
+int
+pgetc2()
+{
+	int c;
+	do {
+		c = pgetc();
+	} while (c == PEOA);
+	return c;
+}
+
+
+static int
+preadfd(void)
+{
+	int nr;
+	char *buf =  parsefile->buf;
+	parsefile->nextc = buf;
+
+retry:
+#ifndef SMALL
+	if (parsefile->fd == 0 && el) {
+		static const char *rl_cp;
+		static int el_len;
+
+		if (rl_cp == NULL)
+			rl_cp = el_gets(el, &el_len);
+		if (rl_cp == NULL)
+			nr = 0;
+		else {
+			nr = el_len;
+			if (nr > IBUFSIZ - 1)
+				nr = IBUFSIZ - 1;
+			memcpy(buf, rl_cp, nr);
+			if (nr != el_len) {
+				el_len -= nr;
+				rl_cp += nr;
+			} else
+				rl_cp = 0;
+		}
+
+	} else
+#endif
+		nr = read(parsefile->fd, buf, IBUFSIZ - 1);
+
+
+	if (nr < 0) {
+		if (errno == EINTR)
+			goto retry;
+		if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
+			int flags = fcntl(0, F_GETFL, 0);
+			if (flags >= 0 && flags & O_NONBLOCK) {
+				flags &=~ O_NONBLOCK;
+				if (fcntl(0, F_SETFL, flags) >= 0) {
+					out2str("sh: turning off NDELAY mode\n");
+					goto retry;
+				}
+			}
+		}
+	}
+	return nr;
+}
+
+/*
+ * Refill the input buffer and return the next input character:
+ *
+ * 1) If a string was pushed back on the input, pop it;
+ * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
+ *    from a string so we can't refill the buffer, return EOF.
+ * 3) If the is more stuff in this buffer, use it else call read to fill it.
+ * 4) Process input up to the next newline, deleting nul characters.
+ */
+
+static int preadbuffer(void)
+{
+	char *q;
+	int more;
+#ifndef SMALL
+	int something;
+#endif
+	char savec;
+
+	if (unlikely(parsefile->strpush)) {
+		if (
+			parsefile->nleft == -1 &&
+			parsefile->strpush->ap &&
+			parsefile->nextc[-1] != ' ' &&
+			parsefile->nextc[-1] != '\t'
+		) {
+			return PEOA;
+		}
+		popstring();
+		return pgetc();
+	}
+	if (unlikely(parsefile->nleft == EOF_NLEFT ||
+		     parsefile->buf == NULL))
+		return PEOF;
+	flushall();
+
+	more = parsefile->lleft;
+	if (more <= 0) {
+again:
+		if ((more = preadfd()) <= 0) {
+			parsefile->lleft = parsefile->nleft = EOF_NLEFT;
+			return PEOF;
+		}
+	}
+
+	q = parsefile->nextc;
+
+	/* delete nul characters */
+#ifndef SMALL
+	something = 0;
+#endif
+	for (;;) {
+		int c;
+
+		more--;
+		c = *q;
+
+		if (!c)
+			memmove(q, q + 1, more);
+		else {
+			q++;
+
+			if (c == '\n') {
+				parsefile->nleft = q - parsefile->nextc - 1;
+				break;
+			}
+
+#ifndef SMALL
+			switch (c) {
+			default:
+				something = 1;
+				/* fall through */
+			case '\t':
+			case ' ':
+				break;
+			}
+#endif
+		}
+
+		if (more <= 0) {
+			parsefile->nleft = q - parsefile->nextc - 1;
+			if (parsefile->nleft < 0)
+				goto again;
+			break;
+		}
+	}
+	parsefile->lleft = more;
+
+	savec = *q;
+	*q = '\0';
+
+#ifndef SMALL
+	if (parsefile->fd == 0 && hist && something) {
+		HistEvent he;
+		INTOFF;
+		history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND,
+			parsefile->nextc);
+		INTON;
+	}
+#endif
+
+	if (vflag) {
+		out2str(parsefile->nextc);
+#ifdef FLUSHERR
+		flushout(out2);
+#endif
+	}
+
+	*q = savec;
+
+	return (signed char)*parsefile->nextc++;
+}
+
+/*
+ * Undo a call to pgetc.  Only two characters may be pushed back.
+ * PEOF may be pushed back.
+ */
+
+void
+pungetc(void)
+{
+	parsefile->unget++;
+}
+
+/*
+ * Push a string back onto the input at this current parsefile level.
+ * We handle aliases this way.
+ */
+void
+pushstring(char *s, void *ap)
+{
+	struct strpush *sp;
+	size_t len;
+
+	len = strlen(s);
+	INTOFF;
+/*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
+	if (parsefile->strpush) {
+		sp = ckmalloc(sizeof (struct strpush));
+		sp->prev = parsefile->strpush;
+		parsefile->strpush = sp;
+	} else
+		sp = parsefile->strpush = &(parsefile->basestrpush);
+	sp->prevstring = parsefile->nextc;
+	sp->prevnleft = parsefile->nleft;
+	sp->unget = parsefile->unget;
+	memcpy(sp->lastc, parsefile->lastc, sizeof(sp->lastc));
+	sp->ap = (struct alias *)ap;
+	if (ap) {
+		((struct alias *)ap)->flag |= ALIASINUSE;
+		sp->string = s;
+	}
+	parsefile->nextc = s;
+	parsefile->nleft = len;
+	parsefile->unget = 0;
+	INTON;
+}
+
+void
+popstring(void)
+{
+	struct strpush *sp = parsefile->strpush;
+
+	INTOFF;
+	if (sp->ap) {
+		if (parsefile->nextc[-1] == ' ' ||
+		    parsefile->nextc[-1] == '\t') {
+			checkkwd |= CHKALIAS;
+		}
+		if (sp->string != sp->ap->val) {
+			ckfree(sp->string);
+		}
+		sp->ap->flag &= ~ALIASINUSE;
+		if (sp->ap->flag & ALIASDEAD) {
+			unalias(sp->ap->name);
+		}
+	}
+	parsefile->nextc = sp->prevstring;
+	parsefile->nleft = sp->prevnleft;
+	parsefile->unget = sp->unget;
+	memcpy(parsefile->lastc, sp->lastc, sizeof(sp->lastc));
+/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
+	parsefile->strpush = sp->prev;
+	if (sp != &(parsefile->basestrpush))
+		ckfree(sp);
+	INTON;
+}
+
+/*
+ * Set the input to take input from a file.  If push is set, push the
+ * old input onto the stack first.
+ */
+
+int
+setinputfile(const char *fname, int flags)
+{
+	int fd;
+
+	INTOFF;
+	if ((fd = open64(fname, O_RDONLY)) < 0) {
+		if (flags & INPUT_NOFILE_OK)
+			goto out;
+		exitstatus = 127;
+		exerror(EXERROR, "Can't open %s", fname);
+	}
+	if (fd < 10)
+		fd = savefd(fd, fd);
+	setinputfd(fd, flags & INPUT_PUSH_FILE);
+out:
+	INTON;
+	return fd;
+}
+
+
+/*
+ * Like setinputfile, but takes an open file descriptor.  Call this with
+ * interrupts off.
+ */
+
+static void
+setinputfd(int fd, int push)
+{
+	if (push) {
+		pushfile();
+		parsefile->buf = 0;
+	}
+	parsefile->fd = fd;
+	if (parsefile->buf == NULL)
+		parsefile->buf = ckmalloc(IBUFSIZ);
+	parsefile->lleft = parsefile->nleft = 0;
+	plinno = 1;
+}
+
+
+/*
+ * Like setinputfile, but takes input from a string.
+ */
+
+void
+setinputstring(char *string)
+{
+	INTOFF;
+	pushfile();
+	parsefile->nextc = string;
+	parsefile->nleft = strlen(string);
+	parsefile->buf = NULL;
+	plinno = 1;
+	INTON;
+}
+
+
+
+/*
+ * To handle the "." command, a stack of input files is used.  Pushfile
+ * adds a new entry to the stack and popfile restores the previous level.
+ */
+
+STATIC void
+pushfile(void)
+{
+	struct parsefile *pf;
+
+	pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
+	pf->prev = parsefile;
+	pf->fd = -1;
+	pf->strpush = NULL;
+	pf->basestrpush.prev = NULL;
+	pf->unget = 0;
+	parsefile = pf;
+}
+
+
+void
+popfile(void)
+{
+	struct parsefile *pf = parsefile;
+
+	INTOFF;
+	if (pf->fd >= 0)
+		close(pf->fd);
+	if (pf->buf)
+		ckfree(pf->buf);
+	while (pf->strpush)
+		popstring();
+	parsefile = pf->prev;
+	ckfree(pf);
+	INTON;
+}
+
+
+void unwindfiles(struct parsefile *stop)
+{
+	while (parsefile != stop)
+		popfile();
+}
+
+
+/*
+ * Return to top level.
+ */
+
+void
+popallfiles(void)
+{
+	unwindfiles(&basepf);
+}
diff --git a/bin/dash/src/input.h b/bin/dash/src/input.h
new file mode 100644
index 00000000..8acc6e9f
--- /dev/null
+++ b/bin/dash/src/input.h
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)input.h	8.2 (Berkeley) 5/4/95
+ */
+
+/* PEOF (the end of file marker) is defined in syntax.h */
+
+enum {
+	INPUT_PUSH_FILE = 1,
+	INPUT_NOFILE_OK = 2,
+};
+
+struct alias;
+
+struct strpush {
+	struct strpush *prev;	/* preceding string on stack */
+	char *prevstring;
+	int prevnleft;
+	struct alias *ap;	/* if push was associated with an alias */
+	char *string;		/* remember the string since it may change */
+
+	/* Remember last two characters for pungetc. */
+	int lastc[2];
+
+	/* Number of outstanding calls to pungetc. */
+	int unget;
+};
+
+/*
+ * The parsefile structure pointed to by the global variable parsefile
+ * contains information about the current file being read.
+ */
+
+struct parsefile {
+	struct parsefile *prev;	/* preceding file on stack */
+	int linno;		/* current line */
+	int fd;			/* file descriptor (or -1 if string) */
+	int nleft;		/* number of chars left in this line */
+	int lleft;		/* number of chars left in this buffer */
+	char *nextc;		/* next char in buffer */
+	char *buf;		/* input buffer */
+	struct strpush *strpush; /* for pushing strings at this level */
+	struct strpush basestrpush; /* so pushing one is fast */
+
+	/* Remember last two characters for pungetc. */
+	int lastc[2];
+
+	/* Number of outstanding calls to pungetc. */
+	int unget;
+};
+
+extern struct parsefile *parsefile;
+
+/*
+ * The input line number.  Input.c just defines this variable, and saves
+ * and restores it when files are pushed and popped.  The user of this
+ * package must set its value.
+ */
+#define plinno (parsefile->linno)
+
+int pgetc(void);
+int pgetc2(void);
+void pungetc(void);
+void pushstring(char *, void *);
+void popstring(void);
+int setinputfile(const char *, int);
+void setinputstring(char *);
+void popfile(void);
+void unwindfiles(struct parsefile *);
+void popallfiles(void);
diff --git a/bin/dash/src/jobs.c b/bin/dash/src/jobs.c
new file mode 100644
index 00000000..5104a5e5
--- /dev/null
+++ b/bin/dash/src/jobs.c
@@ -0,0 +1,1545 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#include <sys/types.h>
+#include <sys/param.h>
+#ifdef BSD
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#include <sys/ioctl.h>
+
+#include "shell.h"
+#if JOBS
+#include <termios.h>
+#undef CEOF			/* syntax.h redefines this */
+#endif
+#include "exec.h"
+#include "eval.h"
+#include "init.h"
+#include "redir.h"
+#include "show.h"
+#include "main.h"
+#include "parser.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "options.h"
+#include "trap.h"
+#include "syntax.h"
+#include "input.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "system.h"
+
+/* mode flags for set_curjob */
+#define CUR_DELETE 2
+#define CUR_RUNNING 1
+#define CUR_STOPPED 0
+
+/* mode flags for dowait */
+#define DOWAIT_NONBLOCK 0
+#define DOWAIT_BLOCK 1
+#define DOWAIT_WAITCMD 2
+
+/* array of jobs */
+static struct job *jobtab;
+/* size of array */
+static unsigned njobs;
+/* pid of last background process */
+pid_t backgndpid;
+
+#if JOBS
+/* pgrp of shell on invocation */
+static int initialpgrp;
+/* control terminal */
+static int ttyfd = -1;
+#endif
+
+/* current job */
+static struct job *curjob;
+
+/* Set if we are in the vforked child */
+int vforked;
+
+STATIC void set_curjob(struct job *, unsigned);
+STATIC int jobno(const struct job *);
+STATIC int sprint_status(char *, int, int);
+STATIC void freejob(struct job *);
+STATIC struct job *getjob(const char *, int);
+STATIC struct job *growjobtab(void);
+STATIC void forkchild(struct job *, union node *, int);
+STATIC void forkparent(struct job *, union node *, int, pid_t);
+STATIC int dowait(int, struct job *);
+#ifdef SYSV
+STATIC int onsigchild(void);
+#endif
+STATIC int waitproc(int, int *);
+STATIC char *commandtext(union node *);
+STATIC void cmdtxt(union node *);
+STATIC void cmdlist(union node *, int);
+STATIC void cmdputs(const char *);
+STATIC void showpipe(struct job *, struct output *);
+STATIC int getstatus(struct job *);
+
+#if JOBS
+static int restartjob(struct job *, int);
+static void xtcsetpgrp(int, pid_t);
+#endif
+
+STATIC void
+set_curjob(struct job *jp, unsigned mode)
+{
+	struct job *jp1;
+	struct job **jpp, **curp;
+
+	/* first remove from list */
+	jpp = curp = &curjob;
+	do {
+		jp1 = *jpp;
+		if (jp1 == jp)
+			break;
+		jpp = &jp1->prev_job;
+	} while (1);
+	*jpp = jp1->prev_job;
+
+	/* Then re-insert in correct position */
+	jpp = curp;
+	switch (mode) {
+	default:
+#ifdef DEBUG
+		abort();
+#endif
+	case CUR_DELETE:
+		/* job being deleted */
+		break;
+	case CUR_RUNNING:
+		/* newly created job or backgrounded job,
+		   put after all stopped jobs. */
+		do {
+			jp1 = *jpp;
+			if (!JOBS || !jp1 || jp1->state != JOBSTOPPED)
+				break;
+			jpp = &jp1->prev_job;
+		} while (1);
+		/* FALLTHROUGH */
+#if JOBS
+	case CUR_STOPPED:
+#endif
+		/* newly stopped job - becomes curjob */
+		jp->prev_job = *jpp;
+		*jpp = jp;
+		break;
+	}
+}
+
+#if JOBS
+/*
+ * Turn job control on and off.
+ *
+ * Note:  This code assumes that the third arg to ioctl is a character
+ * pointer, which is true on Berkeley systems but not System V.  Since
+ * System V doesn't have job control yet, this isn't a problem now.
+ *
+ * Called with interrupts off.
+ */
+
+int jobctl;
+
+void
+setjobctl(int on)
+{
+	int fd;
+	int pgrp;
+
+	if (on == jobctl || rootshell == 0)
+		return;
+	if (on) {
+		int ofd;
+		ofd = fd = open64(_PATH_TTY, O_RDWR);
+		if (fd < 0) {
+			fd += 3;
+			while (!isatty(fd))
+				if (--fd < 0)
+					goto out;
+		}
+		fd = savefd(fd, ofd);
+		do { /* while we are in the background */
+			if ((pgrp = tcgetpgrp(fd)) < 0) {
+out:
+				sh_warnx("can't access tty; job control turned off");
+				mflag = on = 0;
+				goto close;
+			}
+			if (pgrp == getpgrp())
+				break;
+			killpg(0, SIGTTIN);
+		} while (1);
+		initialpgrp = pgrp;
+
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+		setsignal(SIGTTIN);
+		pgrp = rootpid;
+		setpgid(0, pgrp);
+		xtcsetpgrp(fd, pgrp);
+	} else {
+		/* turning job control off */
+		fd = ttyfd;
+		pgrp = initialpgrp;
+		xtcsetpgrp(fd, pgrp);
+		setpgid(0, pgrp);
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+		setsignal(SIGTTIN);
+close:
+		close(fd);
+		fd = -1;
+	}
+	ttyfd = fd;
+	jobctl = on;
+}
+#endif
+
+
+int
+killcmd(argc, argv)
+	int argc;
+	char **argv;
+{
+	extern char *signal_names[];
+	int signo = -1;
+	int list = 0;
+	int i;
+	pid_t pid;
+	struct job *jp;
+
+	if (argc <= 1) {
+usage:
+		sh_error(
+"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
+"kill -l [exitstatus]"
+		);
+	}
+
+	if (**++argv == '-') {
+		signo = decode_signal(*argv + 1, 1);
+		if (signo < 0) {
+			int c;
+
+			while ((c = nextopt("ls:")) != '\0')
+				switch (c) {
+				default:
+#ifdef DEBUG
+					abort();
+#endif
+				case 'l':
+					list = 1;
+					break;
+				case 's':
+					signo = decode_signal(optionarg, 1);
+					if (signo < 0) {
+						sh_error(
+							"invalid signal number or name: %s",
+							optionarg
+						);
+					}
+		                        break;
+				}
+			argv = argptr;
+		} else
+			argv++;
+	}
+
+	if (!list && signo < 0)
+		signo = SIGTERM;
+
+	if ((signo < 0 || !*argv) ^ list) {
+		goto usage;
+	}
+
+	if (list) {
+		struct output *out;
+
+		out = out1;
+		if (!*argv) {
+			outstr("0\n", out);
+			for (i = 1; i < NSIG; i++) {
+				outfmt(out, snlfmt, signal_names[i]);
+			}
+			return 0;
+		}
+		signo = number(*argv);
+		if (signo > 128)
+			signo -= 128;
+		if (0 < signo && signo < NSIG)
+			outfmt(out, snlfmt, signal_names[signo]);
+		else
+			sh_error("invalid signal number or exit status: %s",
+				 *argv);
+		return 0;
+	}
+
+	i = 0;
+	do {
+		if (**argv == '%') {
+			jp = getjob(*argv, 0);
+			pid = -jp->ps[0].pid;
+		} else
+			pid = **argv == '-' ?
+				-number(*argv + 1) : number(*argv);
+		if (kill(pid, signo) != 0) {
+			sh_warnx("%s\n", strerror(errno));
+			i = 1;
+		}
+	} while (*++argv);
+
+	return i;
+}
+
+STATIC int
+jobno(const struct job *jp)
+{
+	return jp - jobtab + 1;
+}
+
+#if JOBS
+int
+fgcmd(int argc, char **argv)
+{
+	struct job *jp;
+	struct output *out;
+	int mode;
+	int retval;
+
+	mode = (**argv == 'f') ? FORK_FG : FORK_BG;
+	nextopt(nullstr);
+	argv = argptr;
+	out = out1;
+	do {
+		jp = getjob(*argv, 1);
+		if (mode == FORK_BG) {
+			set_curjob(jp, CUR_RUNNING);
+			outfmt(out, "[%d] ", jobno(jp));
+		}
+		outstr(jp->ps->cmd, out);
+		showpipe(jp, out);
+		retval = restartjob(jp, mode);
+	} while (*argv && *++argv);
+	return retval;
+}
+
+int bgcmd(int argc, char **argv)
+#ifdef HAVE_ALIAS_ATTRIBUTE
+	__attribute__((__alias__("fgcmd")));
+#else
+{
+	return fgcmd(argc, argv);
+}
+#endif
+
+
+STATIC int
+restartjob(struct job *jp, int mode)
+{
+	struct procstat *ps;
+	int i;
+	int status;
+	pid_t pgid;
+
+	INTOFF;
+	if (jp->state == JOBDONE)
+		goto out;
+	jp->state = JOBRUNNING;
+	pgid = jp->ps->pid;
+	if (mode == FORK_FG)
+		xtcsetpgrp(ttyfd, pgid);
+	killpg(pgid, SIGCONT);
+	ps = jp->ps;
+	i = jp->nprocs;
+	do {
+		if (WIFSTOPPED(ps->status)) {
+			ps->status = -1;
+		}
+	} while (ps++, --i);
+out:
+	status = (mode == FORK_FG) ? waitforjob(jp) : 0;
+	INTON;
+	return status;
+}
+#endif
+
+STATIC int
+sprint_status(char *os, int status, int sigonly)
+{
+	char *s = os;
+	int st;
+
+	st = WEXITSTATUS(status);
+	if (!WIFEXITED(status)) {
+#if JOBS
+		st = WSTOPSIG(status);
+		if (!WIFSTOPPED(status))
+#endif
+			st = WTERMSIG(status);
+		if (sigonly) {
+			if (st == SIGINT || st == SIGPIPE)
+				goto out;
+#if JOBS
+			if (WIFSTOPPED(status))
+				goto out;
+#endif
+		}
+		s = stpncpy(s, strsignal(st), 32);
+#ifdef WCOREDUMP
+		if (WCOREDUMP(status)) {
+			s = stpcpy(s, " (core dumped)");
+		}
+#endif
+	} else if (!sigonly) {
+		if (st)
+			s += fmtstr(s, 16, "Done(%d)", st);
+		else
+			s = stpcpy(s, "Done");
+	}
+
+out:
+	return s - os;
+}
+
+static void
+showjob(struct output *out, struct job *jp, int mode)
+{
+	struct procstat *ps;
+	struct procstat *psend;
+	int col;
+	int indent;
+	char s[80];
+
+	ps = jp->ps;
+
+	if (mode & SHOW_PGID) {
+		/* just output process (group) id of pipeline */
+		outfmt(out, "%d\n", ps->pid);
+		return;
+	}
+
+	col = fmtstr(s, 16, "[%d]   ", jobno(jp));
+	indent = col;
+
+	if (jp == curjob)
+		s[col - 2] = '+';
+	else if (curjob && jp == curjob->prev_job)
+		s[col - 2] = '-';
+
+	if (mode & SHOW_PID)
+		col += fmtstr(s + col, 16, "%d ", ps->pid);
+
+	psend = ps + jp->nprocs;
+
+	if (jp->state == JOBRUNNING) {
+		scopy("Running", s + col);
+		col += strlen("Running");
+	} else {
+		int status = psend[-1].status;
+#if JOBS
+		if (jp->state == JOBSTOPPED)
+			status = jp->stopstatus;
+#endif
+		col += sprint_status(s + col, status, 0);
+	}
+
+	goto start;
+
+	do {
+		/* for each process */
+		col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
+
+start:
+		outfmt(
+			out, "%s%*c%s",
+			s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
+		);
+		if (!(mode & SHOW_PID)) {
+			showpipe(jp, out);
+			break;
+		}
+		if (++ps == psend) {
+			outcslow('\n', out);
+			break;
+		}
+	} while (1);
+
+	jp->changed = 0;
+
+	if (jp->state == JOBDONE) {
+		TRACE(("showjob: freeing job %d\n", jobno(jp)));
+		freejob(jp);
+	}
+}
+
+
+int
+jobscmd(int argc, char **argv)
+{
+	int mode, m;
+	struct output *out;
+
+	mode = 0;
+	while ((m = nextopt("lp")))
+		if (m == 'l')
+			mode = SHOW_PID;
+		else
+			mode = SHOW_PGID;
+
+	out = out1;
+	argv = argptr;
+	if (*argv)
+		do
+			showjob(out, getjob(*argv,0), mode);
+		while (*++argv);
+	else
+		showjobs(out, mode);
+
+	return 0;
+}
+
+
+/*
+ * Print a list of jobs.  If "change" is nonzero, only print jobs whose
+ * statuses have changed since the last call to showjobs.
+ */
+
+void
+showjobs(struct output *out, int mode)
+{
+	struct job *jp;
+
+	TRACE(("showjobs(%x) called\n", mode));
+
+	/* If not even one job changed, there is nothing to do */
+	dowait(DOWAIT_NONBLOCK, NULL);
+
+	for (jp = curjob; jp; jp = jp->prev_job) {
+		if (!(mode & SHOW_CHANGED) || jp->changed)
+			showjob(out, jp, mode);
+	}
+}
+
+/*
+ * Mark a job structure as unused.
+ */
+
+STATIC void
+freejob(struct job *jp)
+{
+	struct procstat *ps;
+	int i;
+
+	INTOFF;
+	for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
+		if (ps->cmd != nullstr)
+			ckfree(ps->cmd);
+	}
+	if (jp->ps != &jp->ps0)
+		ckfree(jp->ps);
+	jp->used = 0;
+	set_curjob(jp, CUR_DELETE);
+	INTON;
+}
+
+
+
+int
+waitcmd(int argc, char **argv)
+{
+	struct job *job;
+	int retval;
+	struct job *jp;
+
+	nextopt(nullstr);
+	retval = 0;
+
+	argv = argptr;
+	if (!*argv) {
+		/* wait for all jobs */
+		for (;;) {
+			jp = curjob;
+			while (1) {
+				if (!jp) {
+					/* no running procs */
+					goto out;
+				}
+				if (jp->state == JOBRUNNING)
+					break;
+				jp->waited = 1;
+				jp = jp->prev_job;
+			}
+			if (!dowait(DOWAIT_WAITCMD, 0))
+				goto sigout;
+		}
+	}
+
+	retval = 127;
+	do {
+		if (**argv != '%') {
+			pid_t pid = number(*argv);
+			job = curjob;
+			goto start;
+			do {
+				if (job->ps[job->nprocs - 1].pid == pid)
+					break;
+				job = job->prev_job;
+start:
+				if (!job)
+					goto repeat;
+			} while (1);
+		} else
+			job = getjob(*argv, 0);
+		/* loop until process terminated or stopped */
+		if (!dowait(DOWAIT_WAITCMD, job))
+			goto sigout;
+		job->waited = 1;
+		retval = getstatus(job);
+repeat:
+		;
+	} while (*++argv);
+
+out:
+	return retval;
+
+sigout:
+	retval = 128 + pending_sig;
+	goto out;
+}
+
+
+
+/*
+ * Convert a job name to a job structure.
+ */
+
+STATIC struct job *
+getjob(const char *name, int getctl)
+{
+	struct job *jp;
+	struct job *found;
+	const char *err_msg = "No such job: %s";
+	unsigned num;
+	int c;
+	const char *p;
+	char *(*match)(const char *, const char *);
+
+	jp = curjob;
+	p = name;
+	if (!p)
+		goto currentjob;
+
+	if (*p != '%')
+		goto err;
+
+	c = *++p;
+	if (!c)
+		goto currentjob;
+
+	if (!p[1]) {
+		if (c == '+' || c == '%') {
+currentjob:
+			err_msg = "No current job";
+			goto check;
+		} else if (c == '-') {
+			if (jp)
+				jp = jp->prev_job;
+			err_msg = "No previous job";
+check:
+			if (!jp)
+				goto err;
+			goto gotit;
+		}
+	}
+
+	if (is_number(p)) {
+		num = atoi(p);
+		if (num > 0 && num <= njobs) {
+			jp = jobtab + num - 1;
+			if (jp->used)
+				goto gotit;
+			goto err;
+		}
+	}
+
+	match = prefix;
+	if (*p == '?') {
+		match = strstr;
+		p++;
+	}
+
+	found = 0;
+	while (jp) {
+		if (match(jp->ps[0].cmd, p)) {
+			if (found)
+				goto err;
+			found = jp;
+			err_msg = "%s: ambiguous";
+		}
+		jp = jp->prev_job;
+	}
+
+	if (!found)
+		goto err;
+	jp = found;
+
+gotit:
+#if JOBS
+	err_msg = "job %s not created under job control";
+	if (getctl && jp->jobctl == 0)
+		goto err;
+#endif
+	return jp;
+err:
+	sh_error(err_msg, name);
+}
+
+
+
+/*
+ * Return a new job structure.
+ * Called with interrupts off.
+ */
+
+struct job *
+makejob(union node *node, int nprocs)
+{
+	int i;
+	struct job *jp;
+
+	for (i = njobs, jp = jobtab ; ; jp++) {
+		if (--i < 0) {
+			jp = growjobtab();
+			break;
+		}
+		if (jp->used == 0)
+			break;
+		if (jp->state != JOBDONE || !jp->waited)
+			continue;
+		if (jobctl)
+			continue;
+		freejob(jp);
+		break;
+	}
+	memset(jp, 0, sizeof(*jp));
+#if JOBS
+	if (jobctl)
+		jp->jobctl = 1;
+#endif
+	jp->prev_job = curjob;
+	curjob = jp;
+	jp->used = 1;
+	jp->ps = &jp->ps0;
+	if (nprocs > 1) {
+		jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
+	}
+	TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
+	    jobno(jp)));
+	return jp;
+}
+
+STATIC struct job *
+growjobtab(void)
+{
+	size_t len;
+	ptrdiff_t offset;
+	struct job *jp, *jq;
+
+	len = njobs * sizeof(*jp);
+	jq = jobtab;
+	jp = ckrealloc(jq, len + 4 * sizeof(*jp));
+
+	offset = (char *)jp - (char *)jq;
+	if (offset) {
+		/* Relocate pointers */
+		size_t l = len;
+
+		jq = (struct job *)((char *)jq + l);
+		while (l) {
+			l -= sizeof(*jp);
+			jq--;
+#define joff(p) ((struct job *)((char *)(p) + l))
+#define jmove(p) (p) = (void *)((char *)(p) + offset)
+			if (likely(joff(jp)->ps == &jq->ps0))
+				jmove(joff(jp)->ps);
+			if (joff(jp)->prev_job)
+				jmove(joff(jp)->prev_job);
+		}
+		if (curjob)
+			jmove(curjob);
+#undef joff
+#undef jmove
+	}
+
+	njobs += 4;
+	jobtab = jp;
+	jp = (struct job *)((char *)jp + len);
+	jq = jp + 3;
+	do {
+		jq->used = 0;
+	} while (--jq >= jp);
+	return jp;
+}
+
+
+/*
+ * Fork off a subshell.  If we are doing job control, give the subshell its
+ * own process group.  Jp is a job structure that the job is to be added to.
+ * N is the command that will be evaluated by the child.  Both jp and n may
+ * be NULL.  The mode parameter can be one of the following:
+ *	FORK_FG - Fork off a foreground process.
+ *	FORK_BG - Fork off a background process.
+ *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
+ *		     process group even if job control is on.
+ *
+ * When job control is turned off, background processes have their standard
+ * input redirected to /dev/null (except for the second and later processes
+ * in a pipeline).
+ *
+ * Called with interrupts off.
+ */
+
+static void forkchild(struct job *jp, union node *n, int mode)
+{
+	int lvforked;
+	int oldlvl;
+
+	TRACE(("Child shell %d\n", getpid()));
+
+	oldlvl = shlvl;
+	lvforked = vforked;
+
+	if (!lvforked) {
+		shlvl++;
+
+		forkreset();
+
+#if JOBS
+		/* do job control only in root shell */
+		jobctl = 0;
+#endif
+	}
+
+#if JOBS
+	if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
+		pid_t pgrp;
+
+		if (jp->nprocs == 0)
+			pgrp = getpid();
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the parent also */
+		(void)setpgid(0, pgrp);
+		if (mode == FORK_FG)
+			xtcsetpgrp(ttyfd, pgrp);
+		setsignal(SIGTSTP);
+		setsignal(SIGTTOU);
+	} else
+#endif
+	if (mode == FORK_BG) {
+		ignoresig(SIGINT);
+		ignoresig(SIGQUIT);
+		if (jp->nprocs == 0) {
+			close(0);
+			if (open64(_PATH_DEVNULL, O_RDONLY) != 0)
+				sh_error("Can't open %s", _PATH_DEVNULL);
+		}
+	}
+	if (!oldlvl && iflag) {
+		if (mode != FORK_BG) {
+			setsignal(SIGINT);
+			setsignal(SIGQUIT);
+		}
+		setsignal(SIGTERM);
+	}
+
+	if (lvforked)
+		return;
+
+	for (jp = curjob; jp; jp = jp->prev_job)
+		freejob(jp);
+}
+
+static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
+{
+	if (pid < 0) {
+		TRACE(("Fork failed, errno=%d", errno));
+		if (jp)
+			freejob(jp);
+		sh_error("Cannot fork");
+		/* NOTREACHED */
+	}
+
+	TRACE(("In parent shell:  child = %d\n", pid));
+	if (!jp)
+		return;
+#if JOBS
+	if (mode != FORK_NOJOB && jp->jobctl) {
+		int pgrp;
+
+		if (jp->nprocs == 0)
+			pgrp = pid;
+		else
+			pgrp = jp->ps[0].pid;
+		/* This can fail because we are doing it in the child also */
+		(void)setpgid(pid, pgrp);
+	}
+#endif
+	if (mode == FORK_BG) {
+		backgndpid = pid;		/* set $! */
+		set_curjob(jp, CUR_RUNNING);
+	}
+	if (jp) {
+		struct procstat *ps = &jp->ps[jp->nprocs++];
+		ps->pid = pid;
+		ps->status = -1;
+		ps->cmd = nullstr;
+		if (jobctl && n)
+			ps->cmd = commandtext(n);
+	}
+}
+
+int
+forkshell(struct job *jp, union node *n, int mode)
+{
+	int pid;
+
+	TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
+	pid = fork();
+	if (pid == 0)
+		forkchild(jp, n, mode);
+	else
+		forkparent(jp, n, mode, pid);
+
+	return pid;
+}
+
+struct job *vforkexec(union node *n, char **argv, const char *path, int idx)
+{
+	struct job *jp;
+	int pid;
+
+	jp = makejob(n, 1);
+
+	sigblockall(NULL);
+	vforked++;
+
+	pid = vfork();
+
+	if (!pid) {
+		forkchild(jp, n, FORK_FG);
+		sigclearmask();
+		shellexec(argv, path, idx);
+		/* NOTREACHED */
+	}
+
+	vforked = 0;
+	sigclearmask();
+	forkparent(jp, n, FORK_FG, pid);
+
+	return jp;
+}
+
+/*
+ * Wait for job to finish.
+ *
+ * Under job control we have the problem that while a child process is
+ * running interrupts generated by the user are sent to the child but not
+ * to the shell.  This means that an infinite loop started by an inter-
+ * active user may be hard to kill.  With job control turned off, an
+ * interactive user may place an interactive program inside a loop.  If
+ * the interactive program catches interrupts, the user doesn't want
+ * these interrupts to also abort the loop.  The approach we take here
+ * is to have the shell ignore interrupt signals while waiting for a
+ * forground process to terminate, and then send itself an interrupt
+ * signal if the child process was terminated by an interrupt signal.
+ * Unfortunately, some programs want to do a bit of cleanup and then
+ * exit on interrupt; unless these processes terminate themselves by
+ * sending a signal to themselves (instead of calling exit) they will
+ * confuse this approach.
+ *
+ * Called with interrupts off.
+ */
+
+int
+waitforjob(struct job *jp)
+{
+	int st;
+
+	TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0));
+	dowait(jp ? DOWAIT_BLOCK : DOWAIT_NONBLOCK, jp);
+	if (!jp)
+		return exitstatus;
+
+	st = getstatus(jp);
+#if JOBS
+	if (jp->jobctl) {
+		xtcsetpgrp(ttyfd, rootpid);
+		/*
+		 * This is truly gross.
+		 * If we're doing job control, then we did a TIOCSPGRP which
+		 * caused us (the shell) to no longer be in the controlling
+		 * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
+		 * intuit from the subprocess exit status whether a SIGINT
+		 * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
+		 */
+		if (jp->sigint)
+			raise(SIGINT);
+	}
+#endif
+	if (! JOBS || jp->state == JOBDONE)
+		freejob(jp);
+	return st;
+}
+
+
+
+/*
+ * Wait for a process to terminate.
+ */
+
+static int waitone(int block, struct job *job)
+{
+	int pid;
+	int status;
+	struct job *jp;
+	struct job *thisjob = NULL;
+	int state;
+
+	INTOFF;
+	TRACE(("dowait(%d) called\n", block));
+	pid = waitproc(block, &status);
+	TRACE(("wait returns pid %d, status=%d\n", pid, status));
+	if (pid <= 0)
+		goto out;
+
+	for (jp = curjob; jp; jp = jp->prev_job) {
+		struct procstat *sp;
+		struct procstat *spend;
+		if (jp->state == JOBDONE)
+			continue;
+		state = JOBDONE;
+		spend = jp->ps + jp->nprocs;
+		sp = jp->ps;
+		do {
+			if (sp->pid == pid) {
+				TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
+				sp->status = status;
+				thisjob = jp;
+			}
+			if (sp->status == -1)
+				state = JOBRUNNING;
+#if JOBS
+			if (state == JOBRUNNING)
+				continue;
+			if (WIFSTOPPED(sp->status)) {
+				jp->stopstatus = sp->status;
+				state = JOBSTOPPED;
+			}
+#endif
+		} while (++sp < spend);
+		if (thisjob)
+			goto gotjob;
+	}
+	goto out;
+
+gotjob:
+	if (state != JOBRUNNING) {
+		thisjob->changed = 1;
+
+		if (thisjob->state != state) {
+			TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
+			thisjob->state = state;
+#if JOBS
+			if (state == JOBSTOPPED) {
+				set_curjob(thisjob, CUR_STOPPED);
+			}
+#endif
+		}
+	}
+
+out:
+	INTON;
+
+	if (thisjob && thisjob == job) {
+		char s[48 + 1];
+		int len;
+
+		len = sprint_status(s, status, 1);
+		if (len) {
+			s[len] = '\n';
+			s[len + 1] = 0;
+			outstr(s, out2);
+		}
+	}
+	return pid;
+}
+
+static int dowait(int block, struct job *jp)
+{
+	int gotchld = *(volatile int *)&gotsigchld;
+	int rpid;
+	int pid;
+
+	if (jp && jp->state != JOBRUNNING)
+		block = DOWAIT_NONBLOCK;
+
+	if (block == DOWAIT_NONBLOCK && !gotchld)
+		return 1;
+
+	rpid = 1;
+
+	do {
+		pid = waitone(block, jp);
+		rpid &= !!pid;
+
+		if (!pid || (jp && jp->state != JOBRUNNING))
+			block = DOWAIT_NONBLOCK;
+	} while (pid >= 0);
+
+	return rpid;
+}
+
+/*
+ * Do a wait system call.  If block is zero, we return -1 rather than
+ * blocking.  If block is DOWAIT_WAITCMD, we return 0 when a signal
+ * other than SIGCHLD interrupted the wait.
+ *
+ * We use sigsuspend in conjunction with a non-blocking wait3 in
+ * order to ensure that waitcmd exits promptly upon the reception
+ * of a signal.
+ *
+ * For code paths other than waitcmd we either use a blocking wait3
+ * or a non-blocking wait3.  For the latter case the caller of dowait
+ * must ensure that it is called over and over again until all dead
+ * children have been reaped.  Otherwise zombies may linger.
+ */
+
+
+STATIC int
+waitproc(int block, int *status)
+{
+	sigset_t oldmask;
+	int flags = block == DOWAIT_BLOCK ? 0 : WNOHANG;
+	int err;
+
+#if JOBS
+	if (jobctl)
+		flags |= WUNTRACED;
+#endif
+
+	do {
+		gotsigchld = 0;
+		do
+			err = wait3(status, flags, NULL);
+		while (err < 0 && errno == EINTR);
+
+		if (err || (err = -!block))
+			break;
+
+		sigblockall(&oldmask);
+
+		while (!gotsigchld && !pending_sig)
+			sigsuspend(&oldmask);
+
+		sigclearmask();
+	} while (gotsigchld);
+
+	return err;
+}
+
+/*
+ * return 1 if there are stopped jobs, otherwise 0
+ */
+int job_warning;
+int
+stoppedjobs(void)
+{
+	struct job *jp;
+	int retval;
+
+	retval = 0;
+	if (job_warning > 1)
+		goto out;
+	jp = curjob;
+	if (jp && jp->state == JOBSTOPPED) {
+		out2str("You have stopped jobs.\n");
+		job_warning++;
+		retval++;
+	}
+
+out:
+	return retval;
+}
+
+/*
+ * Return a string identifying a command (to be printed by the
+ * jobs command).
+ */
+
+STATIC char *cmdnextc;
+
+STATIC char *
+commandtext(union node *n)
+{
+	char *name;
+
+	STARTSTACKSTR(cmdnextc);
+	cmdtxt(n);
+	name = stackblock();
+	TRACE(("commandtext: name %p, end %p\n", name, cmdnextc));
+	return savestr(name);
+}
+
+
+STATIC void
+cmdtxt(union node *n)
+{
+	union node *np;
+	struct nodelist *lp;
+	const char *p;
+	char s[2];
+
+	if (!n)
+		return;
+	switch (n->type) {
+	default:
+#if DEBUG
+		abort();
+#endif
+	case NPIPE:
+		lp = n->npipe.cmdlist;
+		for (;;) {
+			cmdtxt(lp->n);
+			lp = lp->next;
+			if (!lp)
+				break;
+			cmdputs(" | ");
+		}
+		break;
+	case NSEMI:
+		p = "; ";
+		goto binop;
+	case NAND:
+		p = " && ";
+		goto binop;
+	case NOR:
+		p = " || ";
+binop:
+		cmdtxt(n->nbinary.ch1);
+		cmdputs(p);
+		n = n->nbinary.ch2;
+		goto donode;
+	case NREDIR:
+	case NBACKGND:
+		n = n->nredir.n;
+		goto donode;
+	case NNOT:
+		cmdputs("!");
+		n = n->nnot.com;
+donode:
+		cmdtxt(n);
+		break;
+	case NIF:
+		cmdputs("if ");
+		cmdtxt(n->nif.test);
+		cmdputs("; then ");
+		if (n->nif.elsepart) {
+			cmdtxt(n->nif.ifpart);
+			cmdputs("; else ");
+			n = n->nif.elsepart;
+		} else {
+			n = n->nif.ifpart;
+		}
+		p = "; fi";
+		goto dotail;
+	case NSUBSHELL:
+		cmdputs("(");
+		n = n->nredir.n;
+		p = ")";
+		goto dotail;
+	case NWHILE:
+		p = "while ";
+		goto until;
+	case NUNTIL:
+		p = "until ";
+until:
+		cmdputs(p);
+		cmdtxt(n->nbinary.ch1);
+		n = n->nbinary.ch2;
+		p = "; done";
+dodo:
+		cmdputs("; do ");
+dotail:
+		cmdtxt(n);
+		goto dotail2;
+	case NFOR:
+		cmdputs("for ");
+		cmdputs(n->nfor.var);
+		cmdputs(" in ");
+		cmdlist(n->nfor.args, 1);
+		n = n->nfor.body;
+		p = "; done";
+		goto dodo;
+	case NDEFUN:
+		cmdputs(n->ndefun.text);
+		p = "() { ... }";
+		goto dotail2;
+	case NCMD:
+		cmdlist(n->ncmd.args, 1);
+		cmdlist(n->ncmd.redirect, 0);
+		break;
+	case NARG:
+		p = n->narg.text;
+dotail2:
+		cmdputs(p);
+		break;
+	case NHERE:
+	case NXHERE:
+		p = "<<...";
+		goto dotail2;
+	case NCASE:
+		cmdputs("case ");
+		cmdputs(n->ncase.expr->narg.text);
+		cmdputs(" in ");
+		for (np = n->ncase.cases; np; np = np->nclist.next) {
+			cmdtxt(np->nclist.pattern);
+			cmdputs(") ");
+			cmdtxt(np->nclist.body);
+			cmdputs(";; ");
+		}
+		p = "esac";
+		goto dotail2;
+	case NTO:
+		p = ">";
+		goto redir;
+	case NCLOBBER:
+		p = ">|";
+		goto redir;
+	case NAPPEND:
+		p = ">>";
+		goto redir;
+	case NTOFD:
+		p = ">&";
+		goto redir;
+	case NFROM:
+		p = "<";
+		goto redir;
+	case NFROMFD:
+		p = "<&";
+		goto redir;
+	case NFROMTO:
+		p = "<>";
+redir:
+		s[0] = n->nfile.fd + '0';
+		s[1] = '\0';
+		cmdputs(s);
+		cmdputs(p);
+		if (n->type == NTOFD || n->type == NFROMFD) {
+			s[0] = n->ndup.dupfd + '0';
+			p = s;
+			goto dotail2;
+		} else {
+			n = n->nfile.fname;
+			goto donode;
+		}
+	}
+}
+
+STATIC void
+cmdlist(union node *np, int sep)
+{
+	for (; np; np = np->narg.next) {
+		if (!sep)
+			cmdputs(spcstr);
+		cmdtxt(np);
+		if (sep && np->narg.next)
+			cmdputs(spcstr);
+	}
+}
+
+
+STATIC void
+cmdputs(const char *s)
+{
+	const char *p, *str;
+	char cc[2] = " ";
+	char *nextc;
+	signed char c;
+	int subtype = 0;
+	int quoted = 0;
+	static const char vstype[VSTYPE + 1][4] = {
+		"", "}", "-", "+", "?", "=",
+		"%", "%%", "#", "##",
+	};
+
+	nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
+	p = s;
+	while ((c = *p++) != 0) {
+		str = 0;
+		switch (c) {
+		case CTLESC:
+			c = *p++;
+			break;
+		case CTLVAR:
+			subtype = *p++;
+			if ((subtype & VSTYPE) == VSLENGTH)
+				str = "${#";
+			else
+				str = "${";
+			goto dostr;
+		case CTLENDVAR:
+			str = "\"}";
+			str += !(quoted & 1);
+			quoted >>= 1;
+			subtype = 0;
+			goto dostr;
+		case CTLBACKQ:
+			str = "$(...)";
+			goto dostr;
+		case CTLARI:
+			str = "$((";
+			goto dostr;
+		case CTLENDARI:
+			str = "))";
+			goto dostr;
+		case CTLQUOTEMARK:
+			quoted ^= 1;
+			c = '"';
+			break;
+		case '=':
+			if (subtype == 0)
+				break;
+			if ((subtype & VSTYPE) != VSNORMAL)
+				quoted <<= 1;
+			str = vstype[subtype & VSTYPE];
+			if (subtype & VSNUL)
+				c = ':';
+			else
+				goto checkstr;
+			break;
+		case '\'':
+		case '\\':
+		case '"':
+		case '$':
+			/* These can only happen inside quotes */
+			cc[0] = c;
+			str = cc;
+			c = '\\';
+			break;
+		default:
+			break;
+		}
+		USTPUTC(c, nextc);
+checkstr:
+		if (!str)
+			continue;
+dostr:
+		while ((c = *str++)) {
+			USTPUTC(c, nextc);
+		}
+	}
+	if (quoted & 1) {
+		USTPUTC('"', nextc);
+	}
+	*nextc = 0;
+	cmdnextc = nextc;
+}
+
+
+STATIC void
+showpipe(struct job *jp, struct output *out)
+{
+	struct procstat *sp;
+	struct procstat *spend;
+
+	spend = jp->ps + jp->nprocs;
+	for (sp = jp->ps + 1; sp < spend; sp++)
+		outfmt(out, " | %s", sp->cmd);
+	outcslow('\n', out);
+	flushall();
+}
+
+
+#if JOBS
+STATIC void
+xtcsetpgrp(int fd, pid_t pgrp)
+{
+	if (tcsetpgrp(fd, pgrp))
+		sh_error("Cannot set tty process group (%s)", strerror(errno));
+}
+#endif
+
+
+STATIC int
+getstatus(struct job *job) {
+	int status;
+	int retval;
+
+	status = job->ps[job->nprocs - 1].status;
+	retval = WEXITSTATUS(status);
+	if (!WIFEXITED(status)) {
+#if JOBS
+		retval = WSTOPSIG(status);
+		if (!WIFSTOPPED(status))
+#endif
+		{
+			/* XXX: limits number of signals */
+			retval = WTERMSIG(status);
+#if JOBS
+			if (retval == SIGINT)
+				job->sigint = 1;
+#endif
+		}
+		retval += 128;
+	}
+	TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
+		jobno(job), job->nprocs, status, retval));
+	return retval;
+}
diff --git a/bin/dash/src/jobs.h b/bin/dash/src/jobs.h
new file mode 100644
index 00000000..6ac6c56d
--- /dev/null
+++ b/bin/dash/src/jobs.h
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)jobs.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+/* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
+#define FORK_FG 0
+#define FORK_BG 1
+#define FORK_NOJOB 2
+
+/* mode flags for showjob(s) */
+#define	SHOW_PGID	0x01	/* only show pgid - for jobs -p */
+#define	SHOW_PID	0x04	/* include process pid */
+#define	SHOW_CHANGED	0x08	/* only jobs whose state has changed */
+
+
+/*
+ * A job structure contains information about a job.  A job is either a
+ * single process or a set of processes contained in a pipeline.  In the
+ * latter case, pidlist will be non-NULL, and will point to a -1 terminated
+ * array of pids.
+ */
+
+struct procstat {
+	pid_t	pid;		/* process id */
+ 	int	status;		/* last process status from wait() */
+ 	char	*cmd;		/* text of command being run */
+};
+
+struct job {
+	struct procstat ps0;	/* status of process */
+	struct procstat *ps;	/* status or processes when more than one */
+#if JOBS
+	int stopstatus;		/* status of a stopped job */
+#endif
+	uint32_t
+		nprocs: 16,	/* number of processes */
+		state: 8,
+#define	JOBRUNNING	0	/* at least one proc running */
+#define	JOBSTOPPED	1	/* all procs are stopped */
+#define	JOBDONE		2	/* all procs are completed */
+#if JOBS
+		sigint: 1,	/* job was killed by SIGINT */
+		jobctl: 1,	/* job running under job control */
+#endif
+		waited: 1,	/* true if this entry has been waited for */
+		used: 1,	/* true if this entry is in used */
+		changed: 1;	/* true if status has changed */
+	struct job *prev_job;	/* previous job */
+};
+
+union node;
+
+extern pid_t backgndpid;	/* pid of last background process */
+extern int job_warning;		/* user was warned about stopped jobs */
+#if JOBS
+extern int jobctl;		/* true if doing job control */
+#else
+#define jobctl 0
+#endif
+extern int vforked;		/* Set if we are in the vforked child */
+
+void setjobctl(int);
+int killcmd(int, char **);
+int fgcmd(int, char **);
+int bgcmd(int, char **);
+int jobscmd(int, char **);
+struct output;
+void showjobs(struct output *, int);
+int waitcmd(int, char **);
+struct job *makejob(union node *, int);
+int forkshell(struct job *, union node *, int);
+struct job *vforkexec(union node *n, char **argv, const char *path, int idx);
+int waitforjob(struct job *);
+int stoppedjobs(void);
+
+#if ! JOBS
+#define setjobctl(on) ((void)(on))	/* do nothing */
+#endif
diff --git a/bin/dash/src/machdep.h b/bin/dash/src/machdep.h
new file mode 100644
index 00000000..f2ff0ad8
--- /dev/null
+++ b/bin/dash/src/machdep.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)machdep.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*
+ * Most machines require the value returned from malloc to be aligned
+ * in some way.  The following macro will get this right on many machines.
+ */
+
+#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
+/*
+ * It appears that grabstackstr() will barf with such alignments
+ * because stalloc() will return a string allocated in a new stackblock.
+ */
+#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
diff --git a/bin/dash/src/mail.c b/bin/dash/src/mail.c
new file mode 100644
index 00000000..8eacb2d0
--- /dev/null
+++ b/bin/dash/src/mail.c
@@ -0,0 +1,115 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Routines to check for mail.  (Perhaps make part of main.c?)
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "nodes.h"
+#include "exec.h"	/* defines padvance() */
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mail.h"
+#include "mystring.h"
+
+
+#define MAXMBOXES 10
+
+/* times of mailboxes */
+static time_t mailtime[MAXMBOXES];
+/* Set if MAIL or MAILPATH is changed. */
+static int changed;
+
+
+
+/*
+ * Print appropriate message(s) if mail has arrived.  If changed is set,
+ * then the value of MAIL has changed, so we just update the values.
+ */
+
+void
+chkmail(void)
+{
+	const char *mpath;
+	char *p;
+	char *q;
+	time_t *mtp;
+	struct stackmark smark;
+	struct stat64 statb;
+
+	setstackmark(&smark);
+	mpath = mpathset() ? mpathval() : mailval();
+	for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
+		int len;
+
+		len = padvance_magic(&mpath, nullstr, 2);
+		if (!len)
+			break;
+		p = stackblock();
+		if (*p == '\0')
+			continue;
+		for (q = p ; *q ; q++);
+#ifdef DEBUG
+		if (q[-1] != '/')
+			abort();
+#endif
+		q[-1] = '\0';			/* delete trailing '/' */
+		if (stat64(p, &statb) < 0) {
+			*mtp = 0;
+			continue;
+		}
+		if (!changed && statb.st_mtime != *mtp) {
+			outfmt(
+				&errout, snlfmt,
+				pathopt ? pathopt : "you have mail"
+			);
+		}
+		*mtp = statb.st_mtime;
+	}
+	changed = 0;
+	popstackmark(&smark);
+}
+
+
+void
+changemail(const char *val)
+{
+	changed++;
+}
diff --git a/bin/dash/src/mail.h b/bin/dash/src/mail.h
new file mode 100644
index 00000000..3c6b21d2
--- /dev/null
+++ b/bin/dash/src/mail.h
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)mail.h	8.2 (Berkeley) 5/4/95
+ */
+
+void chkmail(void);
+void changemail(const char *);
diff --git a/bin/dash/src/main.c b/bin/dash/src/main.c
new file mode 100644
index 00000000..7a285346
--- /dev/null
+++ b/bin/dash/src/main.c
@@ -0,0 +1,363 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+#include "shell.h"
+#include "main.h"
+#include "mail.h"
+#include "options.h"
+#include "output.h"
+#include "parser.h"
+#include "nodes.h"
+#include "expand.h"
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "trap.h"
+#include "var.h"
+#include "show.h"
+#include "memalloc.h"
+#include "error.h"
+#include "init.h"
+#include "mystring.h"
+#include "exec.h"
+#include "cd.h"
+
+#define PROFILE 0
+
+int rootpid;
+int shlvl;
+#ifdef __GLIBC__
+int *dash_errno;
+#endif
+#if PROFILE
+short profile_buf[16384];
+extern int etext();
+#endif
+MKINIT struct jmploc main_handler;
+
+STATIC void read_profile(const char *);
+STATIC char *find_dot_file(char *);
+static int cmdloop(int);
+int main(int, char **);
+
+/*
+ * Main routine.  We initialize things, parse the arguments, execute
+ * profiles if we're a login shell, and then call cmdloop to execute
+ * commands.  The setjmp call sets up the location to jump to when an
+ * exception occurs.  When an exception occurs the variable "state"
+ * is used to figure out how far we had gotten.
+ */
+
+int
+main(int argc, char **argv)
+{
+	char *shinit;
+	volatile int state;
+	struct stackmark smark;
+	int login;
+
+#ifdef __GLIBC__
+	dash_errno = __errno_location();
+#endif
+
+#if PROFILE
+	monitor(4, etext, profile_buf, sizeof profile_buf, 50);
+#endif
+	state = 0;
+	if (unlikely(setjmp(main_handler.loc))) {
+		int e;
+		int s;
+
+		exitreset();
+
+		e = exception;
+
+		s = state;
+		if (e == EXEND || e == EXEXIT || s == 0 || iflag == 0 || shlvl)
+			exitshell();
+
+		reset();
+
+		if (e == EXINT
+#if ATTY
+		 && (! attyset() || equal(termval(), "emacs"))
+#endif
+		 ) {
+			out2c('\n');
+#ifdef FLUSHERR
+			flushout(out2);
+#endif
+		}
+		popstackmark(&smark);
+		FORCEINTON;				/* enable interrupts */
+		if (s == 1)
+			goto state1;
+		else if (s == 2)
+			goto state2;
+		else if (s == 3)
+			goto state3;
+		else
+			goto state4;
+	}
+	handler = &main_handler;
+#ifdef DEBUG
+	opentrace();
+	trputs("Shell args:  ");  trargs(argv);
+#endif
+	rootpid = getpid();
+	init();
+	setstackmark(&smark);
+	login = procargs(argc, argv);
+	if (login) {
+		state = 1;
+		read_profile("/etc/profile");
+state1:
+		state = 2;
+		read_profile("$HOME/.profile");
+	}
+state2:
+	state = 3;
+	if (
+#ifndef linux
+		getuid() == geteuid() && getgid() == getegid() &&
+#endif
+		iflag
+	) {
+		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
+			read_profile(shinit);
+		}
+	}
+	popstackmark(&smark);
+state3:
+	state = 4;
+	if (minusc)
+		evalstring(minusc, sflag ? 0 : EV_EXIT);
+
+	if (sflag || minusc == NULL) {
+state4:	/* XXX ??? - why isn't this before the "if" statement */
+		cmdloop(1);
+	}
+#if PROFILE
+	monitor(0);
+#endif
+#if GPROF
+	{
+		extern void _mcleanup(void);
+		_mcleanup();
+	}
+#endif
+	exitshell();
+	/* NOTREACHED */
+}
+
+
+/*
+ * Read and execute commands.  "Top" is nonzero for the top level command
+ * loop; it turns on prompting if the shell is interactive.
+ */
+
+static int
+cmdloop(int top)
+{
+	union node *n;
+	struct stackmark smark;
+	int inter;
+	int status = 0;
+	int numeof = 0;
+
+	TRACE(("cmdloop(%d) called\n", top));
+	for (;;) {
+		int skip;
+
+		setstackmark(&smark);
+		if (jobctl)
+			showjobs(out2, SHOW_CHANGED);
+		inter = 0;
+		if (iflag && top) {
+			inter++;
+			chkmail();
+		}
+		n = parsecmd(inter);
+		/* showtree(n); DEBUG */
+		if (n == NEOF) {
+			if (!top || numeof >= 50)
+				break;
+			if (!stoppedjobs()) {
+				if (!Iflag) {
+					if (iflag) {
+						out2c('\n');
+#ifdef FLUSHERR
+						flushout(out2);
+#endif
+					}
+					break;
+				}
+				out2str("\nUse \"exit\" to leave shell.\n");
+			}
+			numeof++;
+		} else if (nflag == 0) {
+			int i;
+
+			job_warning = (job_warning == 2) ? 1 : 0;
+			numeof = 0;
+			i = evaltree(n, 0);
+			if (n)
+				status = i;
+		}
+		popstackmark(&smark);
+
+		skip = evalskip;
+		if (skip) {
+			evalskip &= ~(SKIPFUNC | SKIPFUNCDEF);
+			break;
+		}
+	}
+
+	return status;
+}
+
+
+
+/*
+ * Read /etc/profile or .profile.  Return on error.
+ */
+
+STATIC void
+read_profile(const char *name)
+{
+	name = expandstr(name);
+	if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
+		return;
+
+	cmdloop(0);
+	popfile();
+}
+
+
+
+/*
+ * Read a file containing shell functions.
+ */
+
+void
+readcmdfile(char *name)
+{
+	setinputfile(name, INPUT_PUSH_FILE);
+	cmdloop(0);
+	popfile();
+}
+
+
+
+/*
+ * Take commands from a file.  To be compatible we should do a path
+ * search for the file, which is necessary to find sub-commands.
+ */
+
+
+STATIC char *
+find_dot_file(char *basename)
+{
+	char *fullname;
+	const char *path = pathval();
+	struct stat64 statb;
+	int len;
+
+	/* don't try this for absolute or relative paths */
+	if (strchr(basename, '/'))
+		return basename;
+
+	while ((len = padvance(&path, basename)) >= 0) {
+		fullname = stackblock();
+		if ((!pathopt || *pathopt == 'f') &&
+		    !stat64(fullname, &statb) && S_ISREG(statb.st_mode)) {
+			/* This will be freed by the caller. */
+			return stalloc(len);
+		}
+	}
+
+	/* not found in the PATH */
+	sh_error("%s: not found", basename);
+	/* NOTREACHED */
+}
+
+int
+dotcmd(int argc, char **argv)
+{
+	int status = 0;
+
+	nextopt(nullstr);
+	argv = argptr;
+
+	if (*argv) {
+		char *fullname;
+
+		fullname = find_dot_file(*argv);
+		setinputfile(fullname, INPUT_PUSH_FILE);
+		commandname = fullname;
+		status = cmdloop(0);
+		popfile();
+	}
+
+	return status;
+}
+
+
+int
+exitcmd(int argc, char **argv)
+{
+	if (stoppedjobs())
+		return 0;
+
+	if (argc > 1)
+		savestatus = number(argv[1]);
+
+	exraise(EXEXIT);
+	/* NOTREACHED */
+}
+
+#ifdef mkinit
+INCLUDE "error.h"
+
+FORKRESET {
+	handler = &main_handler;
+}
+#endif
diff --git a/bin/dash/src/main.h b/bin/dash/src/main.h
new file mode 100644
index 00000000..19e49835
--- /dev/null
+++ b/bin/dash/src/main.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)main.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <errno.h>
+
+/* pid of main shell */
+extern int rootpid;
+/* shell level: 0 for the main shell, 1 for its children, and so on */
+extern int shlvl;
+#define rootshell (!shlvl)
+
+#ifdef __GLIBC__
+/* glibc sucks */
+extern int *dash_errno;
+#undef errno
+#define errno (*dash_errno)
+#endif
+
+void readcmdfile(char *);
+int dotcmd(int, char **);
+int exitcmd(int, char **);
diff --git a/bin/dash/src/memalloc.c b/bin/dash/src/memalloc.c
new file mode 100644
index 00000000..60637da1
--- /dev/null
+++ b/bin/dash/src/memalloc.c
@@ -0,0 +1,300 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "shell.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "machdep.h"
+#include "mystring.h"
+#include "system.h"
+
+/*
+ * Like malloc, but returns an error when out of space.
+ */
+
+pointer
+ckmalloc(size_t nbytes)
+{
+	pointer p;
+
+	p = malloc(nbytes);
+	if (p == NULL)
+		sh_error("Out of space");
+	return p;
+}
+
+
+/*
+ * Same for realloc.
+ */
+
+pointer
+ckrealloc(pointer p, size_t nbytes)
+{
+	p = realloc(p, nbytes);
+	if (p == NULL)
+		sh_error("Out of space");
+	return p;
+}
+
+
+/*
+ * Make a copy of a string in safe storage.
+ */
+
+char *
+savestr(const char *s)
+{
+	char *p = strdup(s);
+	if (!p)
+		sh_error("Out of space");
+	return p;
+}
+
+
+/*
+ * Parse trees for commands are allocated in lifo order, so we use a stack
+ * to make this more efficient, and also to avoid all sorts of exception
+ * handling code to handle interrupts in the middle of a parse.
+ *
+ * The size 504 was chosen because the Ultrix malloc handles that size
+ * well.
+ */
+
+/* minimum size of a block */
+#define MINSIZE SHELL_ALIGN(504)
+
+struct stack_block {
+	struct stack_block *prev;
+	char space[MINSIZE];
+};
+
+struct stack_block stackbase;
+struct stack_block *stackp = &stackbase;
+char *stacknxt = stackbase.space;
+size_t stacknleft = MINSIZE;
+char *sstrend = stackbase.space + MINSIZE;
+
+pointer
+stalloc(size_t nbytes)
+{
+	char *p;
+	size_t aligned;
+
+	aligned = SHELL_ALIGN(nbytes);
+	if (aligned > stacknleft) {
+		size_t len;
+		size_t blocksize;
+		struct stack_block *sp;
+
+		blocksize = aligned;
+		if (blocksize < MINSIZE)
+			blocksize = MINSIZE;
+		len = sizeof(struct stack_block) - MINSIZE + blocksize;
+		if (len < blocksize)
+			sh_error("Out of space");
+		INTOFF;
+		sp = ckmalloc(len);
+		sp->prev = stackp;
+		stacknxt = sp->space;
+		stacknleft = blocksize;
+		sstrend = stacknxt + blocksize;
+		stackp = sp;
+		INTON;
+	}
+	p = stacknxt;
+	stacknxt += aligned;
+	stacknleft -= aligned;
+	return p;
+}
+
+
+void
+stunalloc(pointer p)
+{
+#ifdef DEBUG
+	if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
+		write(2, "stunalloc\n", 10);
+		abort();
+	}
+#endif
+	stacknleft += stacknxt - (char *)p;
+	stacknxt = p;
+}
+
+
+
+void pushstackmark(struct stackmark *mark, size_t len)
+{
+	mark->stackp = stackp;
+	mark->stacknxt = stacknxt;
+	mark->stacknleft = stacknleft;
+	grabstackblock(len);
+}
+
+void setstackmark(struct stackmark *mark)
+{
+	pushstackmark(mark, stacknxt == stackp->space && stackp != &stackbase);
+}
+
+
+void
+popstackmark(struct stackmark *mark)
+{
+	struct stack_block *sp;
+
+	INTOFF;
+	while (stackp != mark->stackp) {
+		sp = stackp;
+		stackp = sp->prev;
+		ckfree(sp);
+	}
+	stacknxt = mark->stacknxt;
+	stacknleft = mark->stacknleft;
+	sstrend = mark->stacknxt + mark->stacknleft;
+	INTON;
+}
+
+
+/*
+ * When the parser reads in a string, it wants to stick the string on the
+ * stack and only adjust the stack pointer when it knows how big the
+ * string is.  Stackblock (defined in stack.h) returns a pointer to a block
+ * of space on top of the stack and stackblocklen returns the length of
+ * this block.  Growstackblock will grow this space by at least one byte,
+ * possibly moving it (like realloc).  Grabstackblock actually allocates the
+ * part of the block that has been used.
+ */
+
+static void growstackblock(size_t min)
+{
+	size_t newlen;
+
+	newlen = stacknleft * 2;
+	if (newlen < stacknleft)
+		sh_error("Out of space");
+	min = SHELL_ALIGN(min | 128);
+	if (newlen < min)
+		newlen += min;
+
+	if (stacknxt == stackp->space && stackp != &stackbase) {
+		struct stack_block *sp;
+		struct stack_block *prevstackp;
+		size_t grosslen;
+
+		INTOFF;
+		sp = stackp;
+		prevstackp = sp->prev;
+		grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
+		sp = ckrealloc((pointer)sp, grosslen);
+		sp->prev = prevstackp;
+		stackp = sp;
+		stacknxt = sp->space;
+		stacknleft = newlen;
+		sstrend = sp->space + newlen;
+		INTON;
+	} else {
+		char *oldspace = stacknxt;
+		int oldlen = stacknleft;
+		char *p = stalloc(newlen);
+
+		/* free the space we just allocated */
+		stacknxt = memcpy(p, oldspace, oldlen);
+		stacknleft += newlen;
+	}
+}
+
+/*
+ * The following routines are somewhat easier to use than the above.
+ * The user declares a variable of type STACKSTR, which may be declared
+ * to be a register.  The macro STARTSTACKSTR initializes things.  Then
+ * the user uses the macro STPUTC to add characters to the string.  In
+ * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
+ * grown as necessary.  When the user is done, she can just leave the
+ * string there and refer to it using stackblock().  Or she can allocate
+ * the space for it using grabstackstr().  If it is necessary to allow
+ * someone else to use the stack temporarily and then continue to grow
+ * the string, the user should use grabstack to allocate the space, and
+ * then call ungrabstr(p) to return to the previous mode of operation.
+ *
+ * USTPUTC is like STPUTC except that it doesn't check for overflow.
+ * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
+ * is space for at least one character.
+ */
+
+void *
+growstackstr(void)
+{
+	size_t len = stackblocksize();
+
+	growstackblock(0);
+	return stackblock() + len;
+}
+
+char *growstackto(size_t len)
+{
+	if (stackblocksize() < len)
+		growstackblock(len);
+	return stackblock();
+}
+
+/*
+ * Called from CHECKSTRSPACE.
+ */
+
+char *
+makestrspace(size_t newlen, char *p)
+{
+	size_t len = p - stacknxt;
+
+	return growstackto(len + newlen) + len;
+}
+
+char *
+stnputs(const char *s, size_t n, char *p)
+{
+	p = makestrspace(n, p);
+	p = mempcpy(p, s, n);
+	return p;
+}
+
+char *
+stputs(const char *s, char *p)
+{
+	return stnputs(s, strlen(s), p);
+}
diff --git a/bin/dash/src/memalloc.h b/bin/dash/src/memalloc.h
new file mode 100644
index 00000000..b9adf764
--- /dev/null
+++ b/bin/dash/src/memalloc.h
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)memalloc.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+
+struct stackmark {
+	struct stack_block *stackp;
+	char *stacknxt;
+	size_t stacknleft;
+};
+
+
+extern char *stacknxt;
+extern size_t stacknleft;
+extern char *sstrend;
+
+pointer ckmalloc(size_t);
+pointer ckrealloc(pointer, size_t);
+char *savestr(const char *);
+pointer stalloc(size_t);
+void stunalloc(pointer);
+void pushstackmark(struct stackmark *mark, size_t len);
+void setstackmark(struct stackmark *);
+void popstackmark(struct stackmark *);
+void *growstackstr(void);
+char *growstackto(size_t len);
+char *makestrspace(size_t, char *);
+char *stnputs(const char *, size_t, char *);
+char *stputs(const char *, char *);
+
+
+static inline void grabstackblock(size_t len)
+{
+	stalloc(len);
+}
+
+static inline char *_STPUTC(int c, char *p) {
+	if (p == sstrend)
+		p = growstackstr();
+	*p++ = c;
+	return p;
+}
+
+#define stackblock() ((void *)stacknxt)
+#define stackblocksize() stacknleft
+#define STARTSTACKSTR(p) ((p) = stackblock())
+#define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
+#define CHECKSTRSPACE(n, p) \
+	({ \
+		char *q = (p); \
+		size_t l = (n); \
+		size_t m = sstrend - q; \
+		if (l > m) \
+			(p) = makestrspace(l, q); \
+		0; \
+	})
+#define USTPUTC(c, p)	(*p++ = (c))
+#define STACKSTRNUL(p)	((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
+#define STUNPUTC(p)	(--p)
+#define STTOPC(p)	p[-1]
+#define STADJUST(amount, p)	(p += (amount))
+
+#define grabstackstr(p)	stalloc((char *)(p) - (char *)stackblock())
+#define ungrabstackstr(s, p) stunalloc((s))
+#define stackstrend() ((void *)sstrend)
+
+#define ckfree(p)	free((pointer)(p))
diff --git a/bin/dash/src/miscbltin.c b/bin/dash/src/miscbltin.c
new file mode 100644
index 00000000..5ccbbcb8
--- /dev/null
+++ b/bin/dash/src/miscbltin.c
@@ -0,0 +1,506 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Miscelaneous builtins.
+ */
+
+#include <sys/types.h>		/* quad_t */
+#include <sys/param.h>		/* BSD4_4 */
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <inttypes.h>
+
+#include "shell.h"
+#include "options.h"
+#include "var.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "miscbltin.h"
+#include "mystring.h"
+#include "main.h"
+#include "expand.h"
+#include "parser.h"
+#include "trap.h"
+
+#undef rflag
+
+
+/** handle one line of the read command.
+ *  more fields than variables -> remainder shall be part of last variable.
+ *  less fields than variables -> remaining variables unset.
+ *
+ *  @param line complete line of input
+ *  @param ac argument count
+ *  @param ap argument (variable) list
+ *  @param len length of line including trailing '\0'
+ */
+static void
+readcmd_handle_line(char *s, int ac, char **ap)
+{
+	struct arglist arglist;
+	struct strlist *sl;
+
+	s = grabstackstr(s);
+
+	arglist.lastp = &arglist.list;
+	
+	ifsbreakup(s, ac, &arglist);
+	*arglist.lastp = NULL;
+	ifsfree();
+
+	sl = arglist.list;
+
+	do {
+		if (!sl) {
+			/* nullify remaining arguments */
+			do {
+				setvar(*ap, nullstr, 0);
+			} while (*++ap);
+
+			return;
+		}
+
+		/* set variable to field */
+		rmescapes(sl->text);
+		setvar(*ap, sl->text, 0);
+		sl = sl->next;
+	} while (*++ap);
+}
+
+/*
+ * The read builtin.  The -e option causes backslashes to escape the
+ * following character. The -p option followed by an argument prompts
+ * with the argument.
+ *
+ * This uses unbuffered input, which may be avoidable in some cases.
+ */
+
+int
+readcmd(int argc, char **argv)
+{
+	char **ap;
+	char c;
+	int rflag;
+	char *prompt;
+	char *p;
+	int startloc;
+	int newloc;
+	int status;
+	int i;
+
+	rflag = 0;
+	prompt = NULL;
+	while ((i = nextopt("p:r")) != '\0') {
+		if (i == 'p')
+			prompt = optionarg;
+		else
+			rflag = 1;
+	}
+	if (prompt && isatty(0)) {
+		out2str(prompt);
+#ifdef FLUSHERR
+		flushall();
+#endif
+	}
+	if (*(ap = argptr) == NULL)
+		sh_error("arg count");
+
+	status = 0;
+	STARTSTACKSTR(p);
+
+	goto start;
+
+	for (;;) {
+		switch (read(0, &c, 1)) {
+		case 1:
+			break;
+		default:
+			if (errno == EINTR && !pending_sig)
+				continue;
+				/* fall through */
+		case 0:
+			status = 1;
+			goto out;
+		}
+		if (c == '\0')
+			continue;
+		if (newloc >= startloc) {
+			if (c == '\n')
+				goto resetbs;
+			goto put;
+		}
+		if (!rflag && c == '\\') {
+			newloc = p - (char *)stackblock();
+			continue;
+		}
+		if (c == '\n')
+			break;
+put:
+		CHECKSTRSPACE(2, p);
+		if (strchr(qchars, c))
+			USTPUTC(CTLESC, p);
+		USTPUTC(c, p);
+
+		if (newloc >= startloc) {
+resetbs:
+			recordregion(startloc, newloc, 0);
+start:
+			startloc = p - (char *)stackblock();
+			newloc = startloc - 1;
+		}
+	}
+out:
+	recordregion(startloc, p - (char *)stackblock(), 0);
+	STACKSTRNUL(p);
+	readcmd_handle_line(p + 1, argc - (ap - argv), ap);
+	return status;
+}
+
+
+
+/*
+ * umask builtin
+ *
+ * This code was ripped from pdksh 5.2.14 and hacked for use with
+ * dash by Herbert Xu.
+ *
+ * Public domain.
+ */
+
+int
+umaskcmd(int argc, char **argv)
+{
+	char *ap;
+	int mask;
+	int i;
+	int symbolic_mode = 0;
+
+	while ((i = nextopt("S")) != '\0') {
+		symbolic_mode = 1;
+	}
+
+	INTOFF;
+	mask = umask(0);
+	umask(mask);
+	INTON;
+
+	if ((ap = *argptr) == NULL) {
+		if (symbolic_mode) {
+			char buf[18];
+			int j;
+
+			mask = ~mask;
+			ap = buf;
+			for (i = 0; i < 3; i++) {
+				*ap++ = "ugo"[i];
+				*ap++ = '=';
+				for (j = 0; j < 3; j++)
+					if (mask & (1 << (8 - (3*i + j))))
+						*ap++ = "rwx"[j];
+				*ap++ = ',';
+			}
+			ap[-1] = '\0';
+			out1fmt("%s\n", buf);
+		} else {
+			out1fmt("%.4o\n", mask);
+		}
+	} else {
+		int new_mask;
+
+		if (isdigit((unsigned char) *ap)) {
+			new_mask = 0;
+			do {
+				if (*ap >= '8' || *ap < '0')
+					sh_error(illnum, *argptr);
+				new_mask = (new_mask << 3) + (*ap - '0');
+			} while (*++ap != '\0');
+		} else {
+			int positions, new_val;
+			char op;
+
+			mask = ~mask;
+			new_mask = mask;
+			positions = 0;
+			while (*ap) {
+				while (*ap && strchr("augo", *ap))
+					switch (*ap++) {
+					case 'a': positions |= 0111; break;
+					case 'u': positions |= 0100; break;
+					case 'g': positions |= 0010; break;
+					case 'o': positions |= 0001; break;
+					}
+				if (!positions)
+					positions = 0111; /* default is a */
+				if (!strchr("=+-", op = *ap))
+					break;
+				ap++;
+				new_val = 0;
+				while (*ap && strchr("rwxugoXs", *ap))
+					switch (*ap++) {
+					case 'r': new_val |= 04; break;
+					case 'w': new_val |= 02; break;
+					case 'x': new_val |= 01; break;
+					case 'u': new_val |= mask >> 6;
+						  break;
+					case 'g': new_val |= mask >> 3;
+						  break;
+					case 'o': new_val |= mask >> 0;
+						  break;
+					case 'X': if (mask & 0111)
+							new_val |= 01;
+						  break;
+					case 's': /* ignored */
+						  break;
+					}
+				new_val = (new_val & 07) * positions;
+				switch (op) {
+				case '-':
+					new_mask &= ~new_val;
+					break;
+				case '=':
+					new_mask = new_val
+					    | (new_mask & ~(positions * 07));
+					break;
+				case '+':
+					new_mask |= new_val;
+				}
+				if (*ap == ',') {
+					positions = 0;
+					ap++;
+				} else if (!strchr("=+-", *ap))
+					break;
+			}
+			if (*ap) {
+				sh_error("Illegal mode: %s", *argptr);
+				return 1;
+			}
+			new_mask = ~new_mask;
+		}
+		umask(new_mask);
+	}
+	return 0;
+}
+
+#ifdef HAVE_GETRLIMIT
+/*
+ * ulimit builtin
+ *
+ * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
+ * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
+ * ash by J.T. Conklin.
+ *
+ * Public domain.
+ */
+
+struct limits {
+	const char *name;
+	int	cmd;
+	int	factor;	/* multiply by to get rlim_{cur,max} values */
+	char	option;
+};
+
+static const struct limits limits[] = {
+#ifdef RLIMIT_CPU
+	{ "time(seconds)",		RLIMIT_CPU,	   1, 't' },
+#endif
+#ifdef RLIMIT_FSIZE
+	{ "file(blocks)",		RLIMIT_FSIZE,	 512, 'f' },
+#endif
+#ifdef RLIMIT_DATA
+	{ "data(kbytes)",		RLIMIT_DATA,	1024, 'd' },
+#endif
+#ifdef RLIMIT_STACK
+	{ "stack(kbytes)",		RLIMIT_STACK,	1024, 's' },
+#endif
+#ifdef RLIMIT_CORE
+	{ "coredump(blocks)",		RLIMIT_CORE,	 512, 'c' },
+#endif
+#ifdef RLIMIT_RSS
+	{ "memory(kbytes)",		RLIMIT_RSS,	1024, 'm' },
+#endif
+#ifdef RLIMIT_MEMLOCK
+	{ "locked memory(kbytes)",	RLIMIT_MEMLOCK, 1024, 'l' },
+#endif
+#ifdef RLIMIT_NPROC
+	{ "process",			RLIMIT_NPROC,      1, 'p' },
+#endif
+#ifdef RLIMIT_NOFILE
+	{ "nofiles",			RLIMIT_NOFILE,     1, 'n' },
+#endif
+#ifdef RLIMIT_AS
+	{ "vmemory(kbytes)",		RLIMIT_AS,	1024, 'v' },
+#endif
+#ifdef RLIMIT_LOCKS
+	{ "locks",			RLIMIT_LOCKS,	   1, 'w' },
+#endif
+#ifdef RLIMIT_RTPRIO
+	{ "rtprio",			RLIMIT_RTPRIO,	   1, 'r' },
+#endif
+	{ (char *) 0,			0,		   0,  '\0' }
+};
+
+enum limtype { SOFT = 0x1, HARD = 0x2 };
+
+static void printlim(enum limtype how, const struct rlimit *limit,
+		     const struct limits *l)
+{
+	rlim_t val;
+
+	val = limit->rlim_max;
+	if (how & SOFT)
+		val = limit->rlim_cur;
+
+	if (val == RLIM_INFINITY)
+		out1fmt("unlimited\n");
+	else {
+		val /= l->factor;
+		out1fmt("%" PRIdMAX "\n", (intmax_t) val);
+	}
+}
+
+int
+ulimitcmd(int argc, char **argv)
+{
+	int	c;
+	rlim_t val = 0;
+	enum limtype how = SOFT | HARD;
+	const struct limits	*l;
+	int		set, all = 0;
+	int		optc, what;
+	struct rlimit	limit;
+
+	what = 'f';
+	while ((optc = nextopt("HSa"
+#ifdef RLIMIT_CPU
+			       "t"
+#endif
+#ifdef RLIMIT_FSIZE
+			       "f"
+#endif
+#ifdef RLIMIT_DATA
+			       "d"
+#endif
+#ifdef RLIMIT_STACK
+			       "s"
+#endif
+#ifdef RLIMIT_CORE
+			       "c"
+#endif
+#ifdef RLIMIT_RSS
+			       "m"
+#endif
+#ifdef RLIMIT_MEMLOCK
+			       "l"
+#endif
+#ifdef RLIMIT_NPROC
+			       "p"
+#endif
+#ifdef RLIMIT_NOFILE
+			       "n"
+#endif
+#ifdef RLIMIT_AS
+			       "v"
+#endif
+#ifdef RLIMIT_LOCKS
+			       "w"
+#endif
+	)) != '\0')
+		switch (optc) {
+		case 'H':
+			how = HARD;
+			break;
+		case 'S':
+			how = SOFT;
+			break;
+		case 'a':
+			all = 1;
+			break;
+		default:
+			what = optc;
+		}
+
+	for (l = limits; l->option != what; l++)
+		;
+
+	set = *argptr ? 1 : 0;
+	if (set) {
+		char *p = *argptr;
+
+		if (all || argptr[1])
+			sh_error("too many arguments");
+		if (strcmp(p, "unlimited") == 0)
+			val = RLIM_INFINITY;
+		else {
+			val = (rlim_t) 0;
+
+			while ((c = *p++) >= '0' && c <= '9')
+			{
+				val = (val * 10) + (long)(c - '0');
+				if (val < (rlim_t) 0)
+					break;
+			}
+			if (c)
+				sh_error("bad number");
+			val *= l->factor;
+		}
+	}
+	if (all) {
+		for (l = limits; l->name; l++) {
+			getrlimit(l->cmd, &limit);
+			out1fmt("%-20s ", l->name);
+			printlim(how, &limit, l);
+		}
+		return 0;
+	}
+
+	getrlimit(l->cmd, &limit);
+	if (set) {
+		if (how & HARD)
+			limit.rlim_max = val;
+		if (how & SOFT)
+			limit.rlim_cur = val;
+		if (setrlimit(l->cmd, &limit) < 0)
+			sh_error("error setting limit (%s)", strerror(errno));
+	} else {
+		printlim(how, &limit, l);
+	}
+	return 0;
+}
+#endif
diff --git a/bin/dash/src/miscbltin.h b/bin/dash/src/miscbltin.h
new file mode 100644
index 00000000..dd9a8d1c
--- /dev/null
+++ b/bin/dash/src/miscbltin.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+int readcmd(int, char **);
+int umaskcmd(int, char **);
+int ulimitcmd(int, char **);
diff --git a/bin/dash/src/mkbuiltins b/bin/dash/src/mkbuiltins
new file mode 100644
index 00000000..f1f25932
--- /dev/null
+++ b/bin/dash/src/mkbuiltins
@@ -0,0 +1,120 @@
+#!/bin/sh -
+#	$NetBSD: mkbuiltins,v 1.17 2002/11/24 22:35:41 christos Exp $
+#
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)mkbuiltins	8.2 (Berkeley) 5/4/95
+
+tempfile=mktemp
+if ! type tempfile > /dev/null 2>&1 && ! type mktemp > /dev/null 2>&1; then
+	_my_tempfile()
+	{
+		local index=0
+		while test -f "${TMPDIR:-/tmp}/builtin.$$.$index"; do
+			index=`expr $index + 1`
+		done
+
+		touch "${TMPDIR:-/tmp}/builtin.$$.$index"
+		echo "${TMPDIR:-/tmp}/builtin.$$.$index"
+	}
+
+	tempfile="_my_tempfile"
+elif ! type tempfile > /dev/null 2>&1; then
+	tempfile="mktemp ${TMPDIR:-/tmp}/builtin.XXXXXX"
+fi
+
+trap 'rm -f $temp $temp2' EXIT
+temp=$($tempfile)
+temp2=$($tempfile)
+
+builtins=$1
+
+exec > builtins.c
+cat <<\!
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+#include "shell.h"
+#include "builtins.h"
+
+!
+< $builtins sed '/^#/d; /^ *$/d' > $temp
+awk '{	printf "int %s(int, char **);\n", $1}' $temp
+echo '
+const struct builtincmd builtincmd[] = {'
+awk '{	for (i = 2 ; i <= NF ; i++) {
+		line = $i "\t" $1
+		if ($i ~ /^-/)
+			line = $(++i) "\t" line
+		print line
+	}}' $temp | LC_ALL= LC_COLLATE=C sort -k 1,1 | tee $temp2 | awk '{
+		opt = ""
+		if (NF > 2) {
+			opt = substr($2, 2)
+			$2 = $3
+		}
+		mask = 0
+		cmd = $2
+		if (opt ~ /n/) { cmd = "NULL" }
+		if (opt ~ /s/) { mask += 1 }
+		if (opt ~ /[su]/) { mask += 2 }
+		if (opt ~ /a/) { mask += 4 }
+		printf "\t{ \"%s\", %s, %d },\n", $1, cmd, mask
+	}'
+echo '};'
+
+exec > builtins.h
+cat <<\!
+/*
+ * This file was generated by the mkbuiltins program.
+ */
+
+!
+sed 's/	-[a-z]*//' $temp2 | nl -ba -v0 |
+	LC_ALL= LC_COLLATE=C sort -u -k 3,3 |
+	tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ |
+	awk '{	printf "#define %s (builtincmd + %d)\n", $3, $1}'
+printf '\n#define NUMBUILTINS %d\n' $(wc -l < $temp2)
+echo '
+#define BUILTIN_SPECIAL 0x1
+#define BUILTIN_REGULAR 0x2
+#define BUILTIN_ASSIGN 0x4
+
+struct builtincmd {
+	const char *name;
+	int (*builtin)(int, char **);
+	unsigned flags;
+};
+
+extern const struct builtincmd builtincmd[];'
diff --git a/bin/dash/src/mkinit.c b/bin/dash/src/mkinit.c
new file mode 100644
index 00000000..9025862e
--- /dev/null
+++ b/bin/dash/src/mkinit.c
@@ -0,0 +1,493 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * This program scans all the source files for code to handle various
+ * special events and combines this code into one file.  This (allegedly)
+ * improves the structure of the program since there is no need for
+ * anyone outside of a module to know that that module performs special
+ * operations on particular events.
+ *
+ * Usage:  mkinit sourcefile...
+ */
+
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+/*
+ * OUTFILE is the name of the output file.  Output is initially written
+ * to the file OUTTEMP, which is then moved to OUTFILE.
+ */
+
+#define OUTFILE "init.c"
+#define OUTTEMP "init.c.new"
+
+
+/*
+ * A text structure is basicly just a string that grows as more characters
+ * are added onto the end of it.  It is implemented as a linked list of
+ * blocks of characters.  The routines addstr and addchar append a string
+ * or a single character, respectively, to a text structure.  Writetext
+ * writes the contents of a text structure to a file.
+ */
+
+#define BLOCKSIZE 512
+
+struct text {
+	char *nextc;
+	int nleft;
+	struct block *start;
+	struct block *last;
+};
+
+struct block {
+	struct block *next;
+	char text[BLOCKSIZE];
+};
+
+
+/*
+ * There is one event structure for each event that mkinit handles.
+ */
+
+struct event {
+	char *name;		/* name of event (e.g. INIT) */
+	char *routine;		/* name of routine called on event */
+	char *comment;		/* comment describing routine */
+	struct text code;	/* code for handling event */
+};
+
+
+char writer[] = "\
+/*\n\
+ * This file was generated by the mkinit program.\n\
+ */\n\
+\n";
+
+char init[] = "\
+/*\n\
+ * Initialization code.\n\
+ */\n";
+
+char exitreset[] = "\
+/*\n\
+ * This routine is called when an error or an interrupt occurs in an\n\
+ * interactive shell and control is returned to the main command loop\n\
+ * but prior to exitshell. \n\
+ */\n";
+
+char forkreset[] = "\
+/*\n\
+ * This routine is called when we enter a subshell.\n\
+ */\n";
+
+char reset[] = "\
+/*\n\
+ * This routine is called when an error or an interrupt occurs in an\n\
+ * interactive shell and control is returned to the main command loop.\n\
+ */\n";
+
+
+struct event event[] = {
+	{"INIT", "init", init},
+	{"EXITRESET", "exitreset", exitreset},
+	{"FORKRESET", "forkreset", forkreset},
+	{"RESET", "reset", reset},
+	{NULL, NULL}
+};
+
+
+char *curfile;				/* current file */
+int linno;				/* current line */
+char *header_files[200];		/* list of header files */
+struct text defines;			/* #define statements */
+struct text decls;			/* declarations */
+int amiddecls;				/* for formatting */
+
+
+void readfile(char *);
+int match(char *, char *);
+int gooddefine(char *);
+void doevent(struct event *, FILE *, char *);
+void doinclude(char *);
+void dodecl(char *, FILE *);
+void output(void);
+void addstr(char *, struct text *);
+void addchar(int, struct text *);
+void writetext(struct text *, FILE *);
+FILE *ckfopen(char *, char *);
+void *ckmalloc(int);
+char *savestr(char *);
+static void error(char *);
+int main(int, char **);
+
+#define equal(s1, s2)	(strcmp(s1, s2) == 0)
+
+int
+main(int argc, char **argv)
+{
+	char **ap;
+
+	header_files[0] = "\"shell.h\"";
+	header_files[1] = "\"mystring.h\"";
+	header_files[2] = "\"init.h\"";
+	for (ap = argv + 1 ; *ap ; ap++)
+		readfile(*ap);
+	output();
+	rename(OUTTEMP, OUTFILE);
+	exit(0);
+	/* NOTREACHED */
+}
+
+
+/*
+ * Parse an input file.
+ */
+
+void
+readfile(char *fname)
+{
+	FILE *fp;
+	char line[1024];
+	struct event *ep;
+
+	fp = ckfopen(fname, "r");
+	curfile = fname;
+	linno = 0;
+	amiddecls = 0;
+	while (fgets(line, sizeof line, fp) != NULL) {
+		linno++;
+		for (ep = event ; ep->name ; ep++) {
+			if (line[0] == ep->name[0] && match(ep->name, line)) {
+				doevent(ep, fp, fname);
+				break;
+			}
+		}
+		if (line[0] == 'I' && match("INCLUDE", line))
+			doinclude(line);
+		if (line[0] == 'M' && match("MKINIT", line))
+			dodecl(line, fp);
+		if (line[0] == '#' && gooddefine(line)) {
+		        char *cp;
+			char line2[1024];
+			static const char undef[] = "#undef ";
+
+			strcpy(line2, line);
+			memcpy(line2, undef, sizeof(undef) - 1);
+			cp = line2 + sizeof(undef) - 1;
+			while(*cp && (*cp == ' ' || *cp == '\t'))
+			        cp++;
+			while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
+			        cp++;
+			*cp++ = '\n'; *cp = '\0';
+			addstr(line2, &defines);
+			addstr(line, &defines);
+		}
+	}
+	fclose(fp);
+}
+
+
+int
+match(char *name, char *line)
+{
+	char *p, *q;
+
+	p = name, q = line;
+	while (*p) {
+		if (*p++ != *q++)
+			return 0;
+	}
+	if (*q != '{' && *q != ' ' && *q != '\t' && *q != '\n')
+		return 0;
+	return 1;
+}
+
+
+int
+gooddefine(char *line)
+{
+	char *p;
+
+	if (! match("#define", line))
+		return 0;			/* not a define */
+	p = line + 7;
+	while (*p == ' ' || *p == '\t')
+		p++;
+	while (*p != ' ' && *p != '\t') {
+		if (*p == '(')
+			return 0;		/* macro definition */
+		p++;
+	}
+	while (*p != '\n' && *p != '\0')
+		p++;
+	if (p[-1] == '\\')
+		return 0;			/* multi-line definition */
+	return 1;
+}
+
+
+void
+doevent(struct event *ep, FILE *fp, char *fname)
+{
+	char line[1024];
+	int indent;
+	char *p;
+
+	sprintf(line, "\n      /* from %s: */\n", fname);
+	addstr(line, &ep->code);
+	addstr("      {\n", &ep->code);
+	for (;;) {
+		linno++;
+		if (fgets(line, sizeof line, fp) == NULL)
+			error("Unexpected EOF");
+		if (equal(line, "}\n"))
+			break;
+		indent = 6;
+		for (p = line ; *p == '\t' ; p++)
+			indent += 8;
+		for ( ; *p == ' ' ; p++)
+			indent++;
+		if (*p == '\n' || *p == '#')
+			indent = 0;
+		while (indent >= 8) {
+			addchar('\t', &ep->code);
+			indent -= 8;
+		}
+		while (indent > 0) {
+			addchar(' ', &ep->code);
+			indent--;
+		}
+		addstr(p, &ep->code);
+	}
+	addstr("      }\n", &ep->code);
+}
+
+
+void
+doinclude(char *line)
+{
+	char *p;
+	char *name;
+	char **pp;
+
+	for (p = line ; *p != '"' && *p != '<' && *p != '\0' ; p++);
+	if (*p == '\0')
+		error("Expecting '\"' or '<'");
+	name = p;
+	while (*p != ' ' && *p != '\t' && *p != '\n')
+		p++;
+	if (p[-1] != '"' && p[-1] != '>')
+		error("Missing terminator");
+	*p = '\0';
+
+	/* name now contains the name of the include file */
+	for (pp = header_files ; *pp && ! equal(*pp, name) ; pp++);
+	if (*pp == NULL)
+		*pp = savestr(name);
+}
+
+
+void
+dodecl(char *line1, FILE *fp)
+{
+	char line[1024];
+	char *p, *q;
+
+	if (strcmp(line1, "MKINIT\n") == 0) { /* start of struct/union decl */
+		addchar('\n', &decls);
+		do {
+			linno++;
+			if (fgets(line, sizeof line, fp) == NULL)
+				error("Unterminated structure declaration");
+			addstr(line, &decls);
+		} while (line[0] != '}');
+		amiddecls = 0;
+	} else {
+		if (! amiddecls)
+			addchar('\n', &decls);
+		q = NULL;
+		for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
+			continue;
+		if (*p == '=') {		/* eliminate initialization */
+			for (q = p ; *q && *q != ';' ; q++);
+			if (*q == '\0')
+				q = NULL;
+			else {
+				while (p[-1] == ' ')
+					p--;
+				*p = '\0';
+			}
+		}
+		addstr("extern", &decls);
+		addstr(line1 + 6, &decls);
+		if (q != NULL)
+			addstr(q, &decls);
+		amiddecls = 1;
+	}
+}
+
+
+
+/*
+ * Write the output to the file OUTTEMP.
+ */
+
+void
+output(void)
+{
+	FILE *fp;
+	char **pp;
+	struct event *ep;
+
+	fp = ckfopen(OUTTEMP, "w");
+	fputs(writer, fp);
+	for (pp = header_files ; *pp ; pp++)
+		fprintf(fp, "#include %s\n", *pp);
+	fputs("\n\n\n", fp);
+	writetext(&defines, fp);
+	fputs("\n\n", fp);
+	writetext(&decls, fp);
+	for (ep = event ; ep->name ; ep++) {
+		fputs("\n\n\n", fp);
+		fputs(ep->comment, fp);
+		fprintf(fp, "\nvoid\n%s() {\n", ep->routine);
+		writetext(&ep->code, fp);
+		fprintf(fp, "}\n");
+	}
+	fclose(fp);
+}
+
+
+/*
+ * A text structure is simply a block of text that is kept in memory.
+ * Addstr appends a string to the text struct, and addchar appends a single
+ * character.
+ */
+
+void
+addstr(char *s, struct text *text)
+{
+	while (*s) {
+		if (--text->nleft < 0)
+			addchar(*s++, text);
+		else
+			*text->nextc++ = *s++;
+	}
+}
+
+
+void
+addchar(int c, struct text *text)
+{
+	struct block *bp;
+
+	if (--text->nleft < 0) {
+		bp = ckmalloc(sizeof *bp);
+		if (text->start == NULL)
+			text->start = bp;
+		else
+			text->last->next = bp;
+		text->last = bp;
+		text->nextc = bp->text;
+		text->nleft = BLOCKSIZE - 1;
+	}
+	*text->nextc++ = c;
+}
+
+/*
+ * Write the contents of a text structure to a file.
+ */
+void
+writetext(struct text *text, FILE *fp)
+{
+	struct block *bp;
+
+	if (text->start != NULL) {
+		for (bp = text->start ; bp != text->last ; bp = bp->next) {
+			if ((fwrite(bp->text, sizeof (char), BLOCKSIZE, fp)) != BLOCKSIZE)
+				error("Can't write data\n");
+		}
+		if ((fwrite(bp->text, sizeof (char), BLOCKSIZE - text->nleft, fp)) != (BLOCKSIZE - text->nleft))
+			error("Can't write data\n");
+	}
+}
+
+FILE *
+ckfopen(char *file, char *mode)
+{
+	FILE *fp;
+
+	if ((fp = fopen(file, mode)) == NULL) {
+		fprintf(stderr, "Can't open %s\n", file);
+		exit(2);
+	}
+	return fp;
+}
+
+void *
+ckmalloc(int nbytes)
+{
+	char *p;
+
+	if ((p = malloc(nbytes)) == NULL)
+		error("Out of space");
+	return p;
+}
+
+char *
+savestr(char *s)
+{
+	char *p;
+
+	p = ckmalloc(strlen(s) + 1);
+	strcpy(p, s);
+	return p;
+}
+
+static void
+error(char *msg)
+{
+	if (curfile != NULL)
+		fprintf(stderr, "%s:%d: ", curfile, linno);
+	fprintf(stderr, "%s\n", msg);
+	exit(2);
+	/* NOTREACHED */
+}
diff --git a/bin/dash/src/mknodes.c b/bin/dash/src/mknodes.c
new file mode 100644
index 00000000..1903a605
--- /dev/null
+++ b/bin/dash/src/mknodes.c
@@ -0,0 +1,448 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * This program reads the nodetypes file and nodes.c.pat file.  It generates
+ * the files nodes.h and nodes.c.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#define MAXTYPES 50		/* max number of node types */
+#define MAXFIELDS 20		/* max fields in a structure */
+#define BUFLEN 100		/* size of character buffers */
+
+/* field types */
+#define T_NODE 1		/* union node *field */
+#define T_NODELIST 2		/* struct nodelist *field */
+#define T_STRING 3
+#define T_INT 4			/* int field */
+#define T_OTHER 5		/* other */
+#define T_TEMP 6		/* don't copy this field */
+
+
+struct field {			/* a structure field */
+	char *name;		/* name of field */
+	int type;			/* type of field */
+	char *decl;		/* declaration of field */
+};
+
+
+struct str {			/* struct representing a node structure */
+	char *tag;		/* structure tag */
+	int nfields;		/* number of fields in the structure */
+	struct field field[MAXFIELDS];	/* the fields of the structure */
+	int done;			/* set if fully parsed */
+};
+
+
+static int ntypes;			/* number of node types */
+static char *nodename[MAXTYPES];	/* names of the nodes */
+static struct str *nodestr[MAXTYPES];	/* type of structure used by the node */
+static int nstr;			/* number of structures */
+static struct str str[MAXTYPES];	/* the structures */
+static struct str *curstr;		/* current structure */
+static FILE *infp;
+static char line[1024];
+static int linno;
+static char *linep;
+
+static void parsenode(void);
+static void parsefield(void);
+static void output(char *);
+static void outsizes(FILE *);
+static void outfunc(FILE *, int);
+static void indent(int, FILE *);
+static int nextfield(char *);
+static void skipbl(void);
+static int readline(void);
+static void error(const char *, ...);
+static char *savestr(const char *);
+int main(int, char **);
+
+
+int
+main(int argc, char **argv)
+{
+
+	/*
+	 * some versions of linux complain: initializer element is not
+	 * constant if this is done at compile time.
+	 */
+	infp = stdin;
+
+	if (argc != 3)
+		error("usage: mknodes file");
+	if ((infp = fopen(argv[1], "r")) == NULL)
+		error("Can't open %s", argv[1]);
+	while (readline()) {
+		if (line[0] == ' ' || line[0] == '\t')
+			parsefield();
+		else if (line[0] != '\0')
+			parsenode();
+	}
+	output(argv[2]);
+	exit(0);
+	/* NOTREACHED */
+}
+
+
+
+static void
+parsenode(void)
+{
+	char name[BUFLEN];
+	char tag[BUFLEN];
+	struct str *sp;
+
+	if (curstr && curstr->nfields > 0)
+		curstr->done = 1;
+	nextfield(name);
+	if (! nextfield(tag))
+		error("Tag expected");
+	if (*linep != '\0')
+		error("Garbage at end of line");
+	nodename[ntypes] = savestr(name);
+	for (sp = str ; sp < str + nstr ; sp++) {
+		if (strcmp(sp->tag, tag) == 0)
+			break;
+	}
+	if (sp >= str + nstr) {
+		sp->tag = savestr(tag);
+		sp->nfields = 0;
+		curstr = sp;
+		nstr++;
+	}
+	nodestr[ntypes] = sp;
+	ntypes++;
+}
+
+
+static void
+parsefield(void)
+{
+	char name[BUFLEN];
+	char type[BUFLEN];
+	char decl[2 * BUFLEN];
+	struct field *fp;
+
+	if (curstr == NULL || curstr->done)
+		error("No current structure to add field to");
+	if (! nextfield(name))
+		error("No field name");
+	if (! nextfield(type))
+		error("No field type");
+	fp = &curstr->field[curstr->nfields];
+	fp->name = savestr(name);
+	if (strcmp(type, "nodeptr") == 0) {
+		fp->type = T_NODE;
+		sprintf(decl, "union node *%s", name);
+	} else if (strcmp(type, "nodelist") == 0) {
+		fp->type = T_NODELIST;
+		sprintf(decl, "struct nodelist *%s", name);
+	} else if (strcmp(type, "string") == 0) {
+		fp->type = T_STRING;
+		sprintf(decl, "char *%s", name);
+	} else if (strcmp(type, "int") == 0) {
+		fp->type = T_INT;
+		sprintf(decl, "int %s", name);
+	} else if (strcmp(type, "other") == 0) {
+		fp->type = T_OTHER;
+	} else if (strcmp(type, "temp") == 0) {
+		fp->type = T_TEMP;
+	} else {
+		error("Unknown type %s", type);
+	}
+	if (fp->type == T_OTHER || fp->type == T_TEMP) {
+		skipbl();
+		fp->decl = savestr(linep);
+	} else {
+		if (*linep)
+			error("Garbage at end of line");
+		fp->decl = savestr(decl);
+	}
+	curstr->nfields++;
+}
+
+
+char writer[] = "\
+/*\n\
+ * This file was generated by the mknodes program.\n\
+ */\n\
+\n";
+
+static void
+output(char *file)
+{
+	FILE *hfile;
+	FILE *cfile;
+	FILE *patfile;
+	int i;
+	struct str *sp;
+	struct field *fp;
+	char *p;
+
+	if ((patfile = fopen(file, "r")) == NULL)
+		error("Can't open %s", file);
+	if ((hfile = fopen("nodes.h", "w")) == NULL)
+		error("Can't create nodes.h");
+	if ((cfile = fopen("nodes.c", "w")) == NULL)
+		error("Can't create nodes.c");
+	fputs(writer, hfile);
+	for (i = 0 ; i < ntypes ; i++)
+		fprintf(hfile, "#define %s %d\n", nodename[i], i);
+	fputs("\n\n\n", hfile);
+	for (sp = str ; sp < &str[nstr] ; sp++) {
+		fprintf(hfile, "struct %s {\n", sp->tag);
+		for (i = sp->nfields, fp = sp->field ; --i >= 0 ; fp++) {
+			fprintf(hfile, "      %s;\n", fp->decl);
+		}
+		fputs("};\n\n\n", hfile);
+	}
+	fputs("union node {\n", hfile);
+	fprintf(hfile, "      int type;\n");
+	for (sp = str ; sp < &str[nstr] ; sp++) {
+		fprintf(hfile, "      struct %s %s;\n", sp->tag, sp->tag);
+	}
+	fputs("};\n\n\n", hfile);
+	fputs("struct nodelist {\n", hfile);
+	fputs("\tstruct nodelist *next;\n", hfile);
+	fputs("\tunion node *n;\n", hfile);
+	fputs("};\n\n\n", hfile);
+	fputs("struct funcnode {\n", hfile);
+	fputs("\tint count;\n", hfile);
+	fputs("\tunion node n;\n", hfile);
+	fputs("};\n\n\n", hfile);
+	fputs("struct funcnode *copyfunc(union node *);\n", hfile);
+	fputs("void freefunc(struct funcnode *);\n", hfile);
+
+	fputs(writer, cfile);
+	while (fgets(line, sizeof line, patfile) != NULL) {
+		for (p = line ; *p == ' ' || *p == '\t' ; p++);
+		if (strcmp(p, "%SIZES\n") == 0)
+			outsizes(cfile);
+		else if (strcmp(p, "%CALCSIZE\n") == 0)
+			outfunc(cfile, 1);
+		else if (strcmp(p, "%COPY\n") == 0)
+			outfunc(cfile, 0);
+		else
+			fputs(line, cfile);
+	}
+}
+
+
+
+static void
+outsizes(FILE *cfile)
+{
+	int i;
+
+	fprintf(cfile, "static const short nodesize[%d] = {\n", ntypes);
+	for (i = 0 ; i < ntypes ; i++) {
+		fprintf(cfile, "      SHELL_ALIGN(sizeof (struct %s)),\n",
+		    nodestr[i]->tag);
+	}
+	fprintf(cfile, "};\n");
+}
+
+
+static void
+outfunc(FILE *cfile, int calcsize)
+{
+	struct str *sp;
+	struct field *fp;
+	int i;
+
+	fputs("      if (n == NULL)\n", cfile);
+	if (calcsize)
+		fputs("	    return;\n", cfile);
+	else
+		fputs("	    return NULL;\n", cfile);
+	if (calcsize)
+		fputs("      funcblocksize += nodesize[n->type];\n", cfile);
+	else {
+		fputs("      new = funcblock;\n", cfile);
+		fputs("      funcblock = (char *) funcblock + nodesize[n->type];\n", cfile);
+	}
+	fputs("      switch (n->type) {\n", cfile);
+	for (sp = str ; sp < &str[nstr] ; sp++) {
+		for (i = 0 ; i < ntypes ; i++) {
+			if (nodestr[i] == sp)
+				fprintf(cfile, "      case %s:\n", nodename[i]);
+		}
+		for (i = sp->nfields ; --i >= 1 ; ) {
+			fp = &sp->field[i];
+			switch (fp->type) {
+			case T_NODE:
+				if (calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "calcsize(n->%s.%s);\n",
+						sp->tag, fp->name);
+				} else {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = copynode(n->%s.%s);\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			case T_NODELIST:
+				if (calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "sizenodelist(n->%s.%s);\n",
+						sp->tag, fp->name);
+				} else {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = copynodelist(n->%s.%s);\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			case T_STRING:
+				if (calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "funcstringsize += strlen(n->%s.%s) + 1;\n",
+						sp->tag, fp->name);
+				} else {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = nodesavestr(n->%s.%s);\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			case T_INT:
+			case T_OTHER:
+				if (! calcsize) {
+					indent(12, cfile);
+					fprintf(cfile, "new->%s.%s = n->%s.%s;\n",
+						sp->tag, fp->name, sp->tag, fp->name);
+				}
+				break;
+			}
+		}
+		indent(12, cfile);
+		fputs("break;\n", cfile);
+	}
+	fputs("      };\n", cfile);
+	if (! calcsize)
+		fputs("      new->type = n->type;\n", cfile);
+}
+
+
+static void
+indent(int amount, FILE *fp)
+{
+	while (amount >= 8) {
+		putc('\t', fp);
+		amount -= 8;
+	}
+	while (--amount >= 0) {
+		putc(' ', fp);
+	}
+}
+
+
+static int
+nextfield(char *buf)
+{
+	char *p, *q;
+
+	p = linep;
+	while (*p == ' ' || *p == '\t')
+		p++;
+	q = buf;
+	while (*p != ' ' && *p != '\t' && *p != '\0')
+		*q++ = *p++;
+	*q = '\0';
+	linep = p;
+	return (q > buf);
+}
+
+
+static void
+skipbl(void)
+{
+	while (*linep == ' ' || *linep == '\t')
+		linep++;
+}
+
+
+static int
+readline(void)
+{
+	char *p;
+
+	if (fgets(line, 1024, infp) == NULL)
+		return 0;
+	for (p = line ; *p != '#' && *p != '\n' && *p != '\0' ; p++);
+	while (p > line && (p[-1] == ' ' || p[-1] == '\t'))
+		p--;
+	*p = '\0';
+	linep = line;
+	linno++;
+	if (p - line > BUFLEN)
+		error("Line too long");
+	return 1;
+}
+
+
+
+static void
+error(const char *msg, ...)
+{
+	va_list va;
+
+	va_start(va, msg);
+
+	(void) fprintf(stderr, "line %d: ", linno);
+	(void) vfprintf(stderr, msg, va);
+	(void) fputc('\n', stderr);
+
+	va_end(va);
+
+	exit(2);
+	/* NOTREACHED */
+}
+
+
+
+static char *
+savestr(const char *s)
+{
+	char *p;
+
+	if ((p = malloc(strlen(s) + 1)) == NULL)
+		error("Out of space");
+	(void) strcpy(p, s);
+	return p;
+}
diff --git a/bin/dash/src/mksignames.c b/bin/dash/src/mksignames.c
new file mode 100644
index 00000000..a832eab9
--- /dev/null
+++ b/bin/dash/src/mksignames.c
@@ -0,0 +1,417 @@
+/* signames.c -- Create and write `signames.c', which contains an array of
+   signal names. */
+
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#if !defined (NSIG)
+#  define NSIG 64
+#endif
+
+/*
+ * Special traps:
+ *	EXIT == 0
+ */
+#define LASTSIG NSIG-1
+
+char *signal_names[2 * NSIG + 3];
+
+#define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0]))
+
+char *progname;
+
+/* AIX 4.3 defines SIGRTMIN and SIGRTMAX as 888 and 999 respectively.
+   I don't want to allocate so much unused space for the intervening signal
+   numbers, so we just punt if SIGRTMAX is past the bounds of the
+   signal_names array (handled in configure). */
+#if defined (SIGRTMAX) && defined (UNUSABLE_RT_SIGNALS)
+#  undef SIGRTMAX
+#  undef SIGRTMIN
+#endif
+
+#if defined (SIGRTMAX) || defined (SIGRTMIN)
+#  define RTLEN 14
+#  define RTLIM 256
+#endif
+
+void
+initialize_signames ()
+{
+  register int i;
+#if defined (SIGRTMAX) || defined (SIGRTMIN)
+  int rtmin, rtmax, rtcnt;
+#endif
+
+  for (i = 1; i < signal_names_size; i++)
+    signal_names[i] = (char *)NULL;
+
+  /* `signal' 0 is what we do on exit. */
+  signal_names[0] = "EXIT";
+
+  /* Place signal names which can be aliases for more common signal
+     names first.  This allows (for example) SIGABRT to overwrite SIGLOST. */
+
+  /* POSIX 1003.1b-1993 real time signals, but take care of incomplete
+     implementations. Acoording to the standard, both, SIGRTMIN and
+     SIGRTMAX must be defined, SIGRTMIN must be stricly less than
+     SIGRTMAX, and the difference must be at least 7, that is, there
+     must be at least eight distinct real time signals. */
+
+  /* The generated signal names are SIGRTMIN, SIGRTMIN+1, ...,
+     SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number
+     of RT signals is odd, there is an extra SIGRTMIN+(x+1).
+     These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */
+
+#if defined (SIGRTMIN)
+  rtmin = SIGRTMIN;
+  signal_names[rtmin] = "RTMIN";
+#endif
+
+#if defined (SIGRTMAX)
+  rtmax = SIGRTMAX;
+  signal_names[rtmax] = "RTMAX";
+#endif
+
+#if defined (SIGRTMAX) && defined (SIGRTMIN)
+  if (rtmax > rtmin)
+    {
+      rtcnt = (rtmax - rtmin - 1) / 2;
+      /* croak if there are too many RT signals */
+      if (rtcnt >= RTLIM/2)
+	{
+	  rtcnt = RTLIM/2-1;
+	  fprintf(stderr, "%s: error: more than %i real time signals, fix `%s'\n",
+		  progname, RTLIM, progname);
+	}
+
+      for (i = 1; i <= rtcnt; i++)
+	{
+	  signal_names[rtmin+i] = (char *)malloc(RTLEN);
+	  if (signal_names[rtmin+i])
+	    sprintf (signal_names[rtmin+i], "RTMIN+%d", i);
+	  signal_names[rtmax-i] = (char *)malloc(RTLEN);
+	  if (signal_names[rtmax-i])
+	    sprintf (signal_names[rtmax-i], "RTMAX-%d", i);
+	}
+
+      if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
+	{
+	  /* Need an extra RTMIN signal */
+	  signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
+	  if (signal_names[rtmin+rtcnt+1])
+	    sprintf (signal_names[rtmin+rtcnt+1], "RTMIN+%d", rtcnt+1);
+	}
+    }
+#endif /* SIGRTMIN && SIGRTMAX */
+
+/* AIX */
+#if defined (SIGLOST)	/* resource lost (eg, record-lock lost) */
+  signal_names[SIGLOST] = "LOST";
+#endif
+
+#if defined (SIGMSG)	/* HFT input data pending */
+  signal_names[SIGMSG] = "MSG";
+#endif
+
+#if defined (SIGDANGER)	/* system crash imminent */
+  signal_names[SIGDANGER] = "DANGER";
+#endif
+
+#if defined (SIGMIGRATE) /* migrate process to another CPU */
+  signal_names[SIGMIGRATE] = "MIGRATE";
+#endif
+
+#if defined (SIGPRE)	/* programming error */
+  signal_names[SIGPRE] = "PRE";
+#endif
+
+#if defined (SIGVIRT)	/* AIX virtual time alarm */
+  signal_names[SIGVIRT] = "VIRT";
+#endif
+
+#if defined (SIGALRM1)	/* m:n condition variables */
+  signal_names[SIGALRM1] = "ALRM1";
+#endif
+
+#if defined (SIGWAITING)	/* m:n scheduling */
+  signal_names[SIGWAITING] = "WAITING";
+#endif
+
+#if defined (SIGGRANT)	/* HFT monitor mode granted */
+  signal_names[SIGGRANT] = "GRANT";
+#endif
+
+#if defined (SIGKAP)	/* keep alive poll from native keyboard */
+  signal_names[SIGKAP] = "KAP";
+#endif
+
+#if defined (SIGRETRACT) /* HFT monitor mode retracted */
+  signal_names[SIGRETRACT] = "RETRACT";
+#endif
+
+#if defined (SIGSOUND)	/* HFT sound sequence has completed */
+  signal_names[SIGSOUND] = "SOUND";
+#endif
+
+#if defined (SIGSAK)	/* Secure Attention Key */
+  signal_names[SIGSAK] = "SAK";
+#endif
+
+/* SunOS5 */
+#if defined (SIGLWP)	/* special signal used by thread library */
+  signal_names[SIGLWP] = "LWP";
+#endif
+
+#if defined (SIGFREEZE)	/* special signal used by CPR */
+  signal_names[SIGFREEZE] = "FREEZE";
+#endif
+
+#if defined (SIGTHAW)	/* special signal used by CPR */
+  signal_names[SIGTHAW] = "THAW";
+#endif
+
+#if defined (SIGCANCEL)	/* thread cancellation signal used by libthread */
+  signal_names[SIGCANCEL] = "CANCEL";
+#endif
+
+/* HP-UX */
+#if defined (SIGDIL)	/* DIL signal (?) */
+  signal_names[SIGDIL] = "DIL";
+#endif
+
+/* System V */
+#if defined (SIGCLD)	/* Like SIGCHLD.  */
+  signal_names[SIGCLD] = "CLD";
+#endif
+
+#if defined (SIGPWR)	/* power state indication */
+  signal_names[SIGPWR] = "PWR";
+#endif
+
+#if defined (SIGPOLL)	/* Pollable event (for streams)  */
+  signal_names[SIGPOLL] = "POLL";
+#endif
+
+/* Unknown */
+#if defined (SIGWINDOW)
+  signal_names[SIGWINDOW] = "WINDOW";
+#endif
+
+/* Common */
+#if defined (SIGHUP)	/* hangup */
+  signal_names[SIGHUP] = "HUP";
+#endif
+
+#if defined (SIGINT)	/* interrupt */
+  signal_names[SIGINT] = "INT";
+#endif
+
+#if defined (SIGQUIT)	/* quit */
+  signal_names[SIGQUIT] = "QUIT";
+#endif
+
+#if defined (SIGILL)	/* illegal instruction (not reset when caught) */
+  signal_names[SIGILL] = "ILL";
+#endif
+
+#if defined (SIGTRAP)	/* trace trap (not reset when caught) */
+  signal_names[SIGTRAP] = "TRAP";
+#endif
+
+#if defined (SIGIOT)	/* IOT instruction */
+  signal_names[SIGIOT] = "IOT";
+#endif
+
+#if defined (SIGABRT)	/* Cause current process to dump core. */
+  signal_names[SIGABRT] = "ABRT";
+#endif
+
+#if defined (SIGEMT)	/* EMT instruction */
+  signal_names[SIGEMT] = "EMT";
+#endif
+
+#if defined (SIGFPE)	/* floating point exception */
+  signal_names[SIGFPE] = "FPE";
+#endif
+
+#if defined (SIGKILL)	/* kill (cannot be caught or ignored) */
+  signal_names[SIGKILL] = "KILL";
+#endif
+
+#if defined (SIGBUS)	/* bus error */
+  signal_names[SIGBUS] = "BUS";
+#endif
+
+#if defined (SIGSEGV)	/* segmentation violation */
+  signal_names[SIGSEGV] = "SEGV";
+#endif
+
+#if defined (SIGSYS)	/* bad argument to system call */
+  signal_names[SIGSYS] = "SYS";
+#endif
+
+#if defined (SIGPIPE)	/* write on a pipe with no one to read it */
+  signal_names[SIGPIPE] = "PIPE";
+#endif
+
+#if defined (SIGALRM)	/* alarm clock */
+  signal_names[SIGALRM] = "ALRM";
+#endif
+
+#if defined (SIGTERM)	/* software termination signal from kill */
+  signal_names[SIGTERM] = "TERM";
+#endif
+
+#if defined (SIGURG)	/* urgent condition on IO channel */
+  signal_names[SIGURG] = "URG";
+#endif
+
+#if defined (SIGSTOP)	/* sendable stop signal not from tty */
+  signal_names[SIGSTOP] = "STOP";
+#endif
+
+#if defined (SIGTSTP)	/* stop signal from tty */
+  signal_names[SIGTSTP] = "TSTP";
+#endif
+
+#if defined (SIGCONT)	/* continue a stopped process */
+  signal_names[SIGCONT] = "CONT";
+#endif
+
+#if defined (SIGCHLD)	/* to parent on child stop or exit */
+  signal_names[SIGCHLD] = "CHLD";
+#endif
+
+#if defined (SIGTTIN)	/* to readers pgrp upon background tty read */
+  signal_names[SIGTTIN] = "TTIN";
+#endif
+
+#if defined (SIGTTOU)	/* like TTIN for output if (tp->t_local&LTOSTOP) */
+  signal_names[SIGTTOU] = "TTOU";
+#endif
+
+#if defined (SIGIO)	/* input/output possible signal */
+  signal_names[SIGIO] = "IO";
+#endif
+
+#if defined (SIGXCPU)	/* exceeded CPU time limit */
+  signal_names[SIGXCPU] = "XCPU";
+#endif
+
+#if defined (SIGXFSZ)	/* exceeded file size limit */
+  signal_names[SIGXFSZ] = "XFSZ";
+#endif
+
+#if defined (SIGVTALRM)	/* virtual time alarm */
+  signal_names[SIGVTALRM] = "VTALRM";
+#endif
+
+#if defined (SIGPROF)	/* profiling time alarm */
+  signal_names[SIGPROF] = "PROF";
+#endif
+
+#if defined (SIGWINCH)	/* window changed */
+  signal_names[SIGWINCH] = "WINCH";
+#endif
+
+/* 4.4 BSD */
+#if defined (SIGINFO) && !defined (_SEQUENT_)	/* information request */
+  signal_names[SIGINFO] = "INFO";
+#endif
+
+#if defined (SIGUSR1)	/* user defined signal 1 */
+  signal_names[SIGUSR1] = "USR1";
+#endif
+
+#if defined (SIGUSR2)	/* user defined signal 2 */
+  signal_names[SIGUSR2] = "USR2";
+#endif
+
+#if defined (SIGKILLTHR)	/* BeOS: Kill Thread */
+  signal_names[SIGKILLTHR] = "KILLTHR";
+#endif
+
+  for (i = 0; i < NSIG; i++)
+    if (signal_names[i] == (char *)NULL)
+      {
+	signal_names[i] = (char *)malloc (18);
+	if (signal_names[i])
+	  sprintf (signal_names[i], "%d", i);
+      }
+}
+
+void
+write_signames (stream)
+     FILE *stream;
+{
+  register int i;
+
+  fprintf (stream, "/* This file was automatically created by %s.\n",
+	   progname);
+  fprintf (stream, "   Do not edit.  Edit support/mksignames.c instead. */\n\n");
+  fprintf (stream, "#include <signal.h>\n\n");
+  fprintf (stream,
+	   "/* A translation list so we can be polite to our users. */\n");
+  fprintf (stream, "const char *const signal_names[NSIG + 1] = {\n");
+
+  for (i = 0; i <= LASTSIG; i++)
+    fprintf (stream, "    \"%s\",\n", signal_names[i]);
+
+  fprintf (stream, "    (char *)0x0\n");
+  fprintf (stream, "};\n");
+}
+
+int
+main(int argc, char **argv)
+{
+  char *stream_name;
+  FILE *stream;
+
+  progname = argv[0];
+
+  if (argc == 1)
+    {
+      stream_name = "signames.c";
+    }
+  else if (argc == 2)
+    {
+      stream_name = argv[1];
+    }
+  else
+    {
+      fprintf (stderr, "Usage: %s [output-file]\n", progname);
+      exit (1);
+    }
+
+  stream = fopen (stream_name, "w");
+  if (!stream)
+    {
+      fprintf (stderr, "%s: %s: cannot open for writing\n",
+	       progname, stream_name);
+      exit (2);
+    }
+
+  initialize_signames ();
+  write_signames (stream);
+  exit (0);
+}
diff --git a/bin/dash/src/mksyntax.c b/bin/dash/src/mksyntax.c
new file mode 100644
index 00000000..a23c18ca
--- /dev/null
+++ b/bin/dash/src/mksyntax.c
@@ -0,0 +1,315 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * This program creates syntax.h and syntax.c.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "parser.h"
+
+
+struct synclass {
+	char *name;
+	char *comment;
+};
+
+/* Syntax classes */
+struct synclass synclass[] = {
+	{ "CWORD",	"character is nothing special" },
+	{ "CNL",	"newline character" },
+	{ "CBACK",	"a backslash character" },
+	{ "CSQUOTE",	"single quote" },
+	{ "CDQUOTE",	"double quote" },
+	{ "CENDQUOTE",	"a terminating quote" },
+	{ "CBQUOTE",	"backwards single quote" },
+	{ "CVAR",	"a dollar sign" },
+	{ "CENDVAR",	"a '}' character" },
+	{ "CLP",	"a left paren in arithmetic" },
+	{ "CRP",	"a right paren in arithmetic" },
+	{ "CEOF",	"end of file" },
+	{ "CCTL",	"like CWORD, except it must be escaped" },
+	{ "CSPCL",	"these terminate a word" },
+	{ "CIGN",	"character should be ignored" },
+	{ NULL,		NULL }
+};
+
+
+/*
+ * Syntax classes for is_ functions.  Warning:  if you add new classes
+ * you may have to change the definition of the is_in_name macro.
+ */
+struct synclass is_entry[] = {
+	{ "ISDIGIT",	"a digit" },
+	{ "ISUPPER",	"an upper case letter" },
+	{ "ISLOWER",	"a lower case letter" },
+	{ "ISUNDER",	"an underscore" },
+	{ "ISSPECL",	"the name of a special parameter" },
+	{ NULL, 	NULL }
+};
+
+static char writer[] = "\
+/*\n\
+ * This file was generated by the mksyntax program.\n\
+ */\n\
+\n";
+
+
+static FILE *cfile;
+static FILE *hfile;
+static char *syntax[513];
+
+static void filltable(char *);
+static void init(void);
+static void add(char *, char *);
+static void print(char *);
+static void output_type_macros(void);
+int main(int, char **);
+
+int
+main(int argc, char **argv)
+{
+	int i;
+	char buf[80];
+	int pos;
+
+	/* Create output files */
+	if ((cfile = fopen("syntax.c", "w")) == NULL) {
+		perror("syntax.c");
+		exit(2);
+	}
+	if ((hfile = fopen("syntax.h", "w")) == NULL) {
+		perror("syntax.h");
+		exit(2);
+	}
+	fputs(writer, hfile);
+	fputs(writer, cfile);
+
+	fputs("#include <ctype.h>\n", hfile);
+	fputs("\n", hfile);
+	fputs("#ifdef CEOF\n", hfile);
+	fputs("#undef CEOF\n", hfile);
+	fputs("#endif\n", hfile);
+	fputs("\n", hfile);
+
+	/* Generate the #define statements in the header file */
+	fputs("/* Syntax classes */\n", hfile);
+	for (i = 0 ; synclass[i].name ; i++) {
+		sprintf(buf, "#define %s %d", synclass[i].name, i);
+		fputs(buf, hfile);
+		for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
+			putc('\t', hfile);
+		fprintf(hfile, "/* %s */\n", synclass[i].comment);
+	}
+	putc('\n', hfile);
+	fputs("/* Syntax classes for is_ functions */\n", hfile);
+	for (i = 0 ; is_entry[i].name ; i++) {
+		sprintf(buf, "#define %s %#o", is_entry[i].name, 1 << i);
+		fputs(buf, hfile);
+		for (pos = strlen(buf) ; pos < 32 ; pos = (pos + 8) & ~07)
+			putc('\t', hfile);
+		fprintf(hfile, "/* %s */\n", is_entry[i].comment);
+	}
+	putc('\n', hfile);
+	fprintf(hfile, "#define SYNBASE %d\n", 130);
+	fprintf(hfile, "#define PEOF %d\n\n", -130);
+	fprintf(hfile, "#define PEOA %d\n\n", -129);
+	putc('\n', hfile);
+	fputs("#define BASESYNTAX (basesyntax + SYNBASE)\n", hfile);
+	fputs("#define DQSYNTAX (dqsyntax + SYNBASE)\n", hfile);
+	fputs("#define SQSYNTAX (sqsyntax + SYNBASE)\n", hfile);
+	fputs("#define ARISYNTAX (arisyntax + SYNBASE)\n", hfile);
+	putc('\n', hfile);
+	output_type_macros();		/* is_digit, etc. */
+	putc('\n', hfile);
+
+	/* Generate the syntax tables. */
+	fputs("#include \"shell.h\"\n", cfile);
+	fputs("#include \"syntax.h\"\n\n", cfile);
+	init();
+	fputs("/* syntax table used when not in quotes */\n", cfile);
+	add("\n", "CNL");
+	add("\\", "CBACK");
+	add("'", "CSQUOTE");
+	add("\"", "CDQUOTE");
+	add("`", "CBQUOTE");
+	add("$", "CVAR");
+	add("}", "CENDVAR");
+	add("<>();&| \t", "CSPCL");
+	syntax[1] = "CSPCL";
+	print("basesyntax");
+	init();
+	fputs("\n/* syntax table used when in double quotes */\n", cfile);
+	add("\n", "CNL");
+	add("\\", "CBACK");
+	add("\"", "CENDQUOTE");
+	add("`", "CBQUOTE");
+	add("$", "CVAR");
+	add("}", "CENDVAR");
+	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+	add("!*?[=~:/-]", "CCTL");
+	print("dqsyntax");
+	init();
+	fputs("\n/* syntax table used when in single quotes */\n", cfile);
+	add("\n", "CNL");
+	add("'", "CENDQUOTE");
+	/* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */
+	add("!*?[=~:/-]\\", "CCTL");
+	print("sqsyntax");
+	init();
+	fputs("\n/* syntax table used when in arithmetic */\n", cfile);
+	add("\n", "CNL");
+	add("\\", "CBACK");
+	add("`", "CBQUOTE");
+	add("$", "CVAR");
+	add("}", "CENDVAR");
+	add("(", "CLP");
+	add(")", "CRP");
+	print("arisyntax");
+	filltable("0");
+	fputs("\n/* character classification table */\n", cfile);
+	add("0123456789", "ISDIGIT");
+	add("abcdefghijklmnopqrstucvwxyz", "ISLOWER");
+	add("ABCDEFGHIJKLMNOPQRSTUCVWXYZ", "ISUPPER");
+	add("_", "ISUNDER");
+	add("#?$!-*@", "ISSPECL");
+	print("is_type");
+	exit(0);
+	/* NOTREACHED */
+}
+
+
+
+/*
+ * Clear the syntax table.
+ */
+
+static void
+filltable(char *dftval)
+{
+	int i;
+
+	for (i = 0 ; i < 258; i++)
+		syntax[i] = dftval;
+}
+
+
+/*
+ * Initialize the syntax table with default values.
+ */
+
+static void
+init(void)
+{
+	int ctl;
+
+	filltable("CWORD");
+	syntax[0] = "CEOF";
+	syntax[1] = "CIGN";
+	for (ctl = CTL_FIRST; ctl <= CTL_LAST; ctl++ )
+		syntax[130 + ctl] = "CCTL";
+}
+
+
+/*
+ * Add entries to the syntax table.
+ */
+
+static void
+add(char *p, char *type)
+{
+	while (*p)
+		syntax[(signed char)*p++ + 130] = type;
+}
+
+
+
+/*
+ * Output the syntax table.
+ */
+
+static void
+print(char *name)
+{
+	int i;
+	int col;
+
+	fprintf(hfile, "extern const char %s[];\n", name);
+	fprintf(cfile, "const char %s[] = {\n", name);
+	col = 0;
+	for (i = 0 ; i < 258; i++) {
+		if (i == 0) {
+			fputs("      ", cfile);
+		} else if ((i & 03) == 0) {
+			fputs(",\n      ", cfile);
+			col = 0;
+		} else {
+			putc(',', cfile);
+			while (++col < 9 * (i & 03))
+				putc(' ', cfile);
+		}
+		fputs(syntax[i], cfile);
+		col += strlen(syntax[i]);
+	}
+	fputs("\n};\n", cfile);
+}
+
+
+
+/*
+ * Output character classification macros (e.g. is_digit).  If digits are
+ * contiguous, we can test for them quickly.
+ */
+
+static char *macro[] = {
+	"#define is_digit(c)\t((unsigned)((c) - '0') <= 9)\n",
+	"#define is_alpha(c)\tisalpha((unsigned char)(c))\n",
+	"#define is_name(c)\t((c) == '_' || isalpha((unsigned char)(c)))\n",
+	"#define is_in_name(c)\t((c) == '_' || isalnum((unsigned char)(c)))\n",
+	"#define is_special(c)\t((is_type+SYNBASE)[(signed char)(c)] & (ISSPECL|ISDIGIT))\n",
+	NULL
+};
+
+static void
+output_type_macros(void)
+{
+	char **pp;
+
+	for (pp = macro ; *pp ; pp++)
+		fputs(*pp, hfile);
+	fputs("#define digit_val(c)\t((c) - '0')\n", hfile);
+}
diff --git a/bin/dash/src/mktokens b/bin/dash/src/mktokens
new file mode 100644
index 00000000..78055be8
--- /dev/null
+++ b/bin/dash/src/mktokens
@@ -0,0 +1,97 @@
+#!/bin/sh -
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)mktokens	8.1 (Berkeley) 5/31/93
+
+# 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
+# error messages.
+
+: "${TMPDIR:=/tmp}"
+
+cat > "${TMPDIR}"/ka$$ <<\!
+TEOF	1	end of file
+TNL	0	newline
+TSEMI	0	";"
+TBACKGND 0	"&"
+TAND	0	"&&"
+TOR	0	"||"
+TPIPE	0	"|"
+TLP	0	"("
+TRP	1	")"
+TENDCASE 1	";;"
+TENDBQUOTE 1	"`"
+TREDIR	0	redirection
+TWORD	0	word
+TNOT	0	"!"
+TCASE	0	"case"
+TDO	1	"do"
+TDONE	1	"done"
+TELIF	1	"elif"
+TELSE	1	"else"
+TESAC	1	"esac"
+TFI	1	"fi"
+TFOR	0	"for"
+TIF	0	"if"
+TIN	0	"in"
+TTHEN	1	"then"
+TUNTIL	0	"until"
+TWHILE	0	"while"
+TBEGIN	0	"{"
+TEND	1	"}"
+!
+nl=`wc -l "${TMPDIR}"/ka$$`
+exec > token.h
+awk '{print "#define " $1 " " NR-1}' "${TMPDIR}"/ka$$
+
+exec > token_vars.h
+
+echo '
+/* Array indicating which tokens mark the end of a list */
+static const char tokendlist[] = {'
+awk '{print "\t" $2 ","}' "${TMPDIR}"/ka$$
+echo '};
+
+static const char *const tokname[] = {'
+sed -e 's/"/\\"/g' \
+    -e 's/[^	 ]*[	 ][	 ]*[^	 ]*[	 ][	 ]*\(.*\)/	"\1",/' \
+    "${TMPDIR}"/ka$$
+echo '};
+'
+sed 's/"//g' "${TMPDIR}"/ka$$ | awk '
+/TNOT/{print "#define KWDOFFSET " NR-1; print ""; 
+      print "static const char *const parsekwd[] = {"}
+/TNOT/,/neverfound/{if (last) print "	\"" last "\","; last = $3}
+END{print "	\"" last "\"\n};"}'
+
+rm "${TMPDIR}"/ka$$
diff --git a/bin/dash/src/myhistedit.h b/bin/dash/src/myhistedit.h
new file mode 100644
index 00000000..22e5c438
--- /dev/null
+++ b/bin/dash/src/myhistedit.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)myhistedit.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <histedit.h>
+
+extern History *hist;
+extern EditLine *el;
+extern int displayhist;
+
+void histedit(void);
+void sethistsize(const char *);
+void setterm(const char *);
+int histcmd(int, char **);
+int not_fcnumber(char *);
+int str_to_event(const char *, int);
+
diff --git a/bin/dash/src/mystring.c b/bin/dash/src/mystring.c
new file mode 100644
index 00000000..de624b89
--- /dev/null
+++ b/bin/dash/src/mystring.c
@@ -0,0 +1,257 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * String functions.
+ *
+ *	equal(s1, s2)		Return true if strings are equal.
+ *	scopy(from, to)		Copy a string.
+ *	scopyn(from, to, n)	Like scopy, but checks for overflow.
+ *	number(s)		Convert a string of digits to an integer.
+ *	is_number(s)		Return true if s is a string of digits.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include "shell.h"
+#include "syntax.h"
+#include "error.h"
+#include "mystring.h"
+#include "memalloc.h"
+#include "parser.h"
+#include "system.h"
+
+
+char nullstr[1];		/* zero length string */
+const char spcstr[] = " ";
+const char snlfmt[] = "%s\n";
+const char dolatstr[] = { CTLQUOTEMARK, CTLVAR, VSNORMAL, '@', '=',
+			  CTLQUOTEMARK, '\0' };
+const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
+const char illnum[] = "Illegal number: %s";
+const char homestr[] = "HOME";
+
+/*
+ * equal - #defined in mystring.h
+ */
+
+/*
+ * scopy - #defined in mystring.h
+ */
+
+
+#if 0
+/*
+ * scopyn - copy a string from "from" to "to", truncating the string
+ *		if necessary.  "To" is always nul terminated, even if
+ *		truncation is performed.  "Size" is the size of "to".
+ */
+
+void
+scopyn(const char *from, char *to, int size)
+{
+
+	while (--size > 0) {
+		if ((*to++ = *from++) == '\0')
+			return;
+	}
+	*to = '\0';
+}
+#endif
+
+
+/*
+ * prefix -- see if pfx is a prefix of string.
+ */
+
+char *
+prefix(const char *string, const char *pfx)
+{
+	while (*pfx) {
+		if (*pfx++ != *string++)
+			return 0;
+	}
+	return (char *) string;
+}
+
+void badnum(const char *s)
+{
+	sh_error(illnum, s);
+}
+
+/*
+ * Convert a string into an integer of type intmax_t.  Alow trailing spaces.
+ */
+intmax_t atomax(const char *s, int base)
+{
+	char *p;
+	intmax_t r;
+
+	errno = 0;
+	r = strtoimax(s, &p, base);
+
+	if (errno == ERANGE)
+		badnum(s);
+
+	/*
+	 * Disallow completely blank strings in non-arithmetic (base != 0)
+	 * contexts.
+	 */
+	if (p == s && base)
+		badnum(s);
+
+	while (isspace((unsigned char)*p))
+	      p++;
+
+	if (*p)
+		badnum(s);
+
+	return r;
+}
+
+intmax_t atomax10(const char *s)
+{
+	return atomax(s, 10);
+}
+
+/*
+ * Convert a string of digits to an integer, printing an error message on
+ * failure.
+ */
+
+int
+number(const char *s)
+{
+	intmax_t n = atomax10(s);
+
+	if (n < 0 || n > INT_MAX)
+		badnum(s);
+
+	return n;
+}
+
+
+
+/*
+ * Check for a valid number.  This should be elsewhere.
+ */
+
+int
+is_number(const char *p)
+{
+	do {
+		if (! is_digit(*p))
+			return 0;
+	} while (*++p != '\0');
+	return 1;
+}
+
+
+/*
+ * Produce a possibly single quoted string suitable as input to the shell.
+ * The return string is allocated on the stack.
+ */
+
+char *
+single_quote(const char *s) {
+	char *p;
+
+	STARTSTACKSTR(p);
+
+	do {
+		char *q;
+		size_t len;
+
+		len = strchrnul(s, '\'') - s;
+
+		q = p = makestrspace(len + 3, p);
+
+		*q++ = '\'';
+		q = mempcpy(q, s, len);
+		*q++ = '\'';
+		s += len;
+
+		STADJUST(q - p, p);
+
+		len = strspn(s, "'");
+		if (!len)
+			break;
+
+		q = p = makestrspace(len + 3, p);
+
+		*q++ = '"';
+		q = mempcpy(q, s, len);
+		*q++ = '"';
+		s += len;
+
+		STADJUST(q - p, p);
+	} while (*s);
+
+	USTPUTC(0, p);
+
+	return stackblock();
+}
+
+/*
+ * Like strdup but works with the ash stack.
+ */
+
+char *
+sstrdup(const char *p)
+{
+	size_t len = strlen(p) + 1;
+	return memcpy(stalloc(len), p, len);
+}
+
+/*
+ * Wrapper around strcmp for qsort/bsearch/...
+ */
+int
+pstrcmp(const void *a, const void *b)
+{
+	return strcmp(*(const char *const *) a, *(const char *const *) b);
+}
+
+/*
+ * Find a string is in a sorted array.
+ */
+const char *const *
+findstring(const char *s, const char *const *array, size_t nmemb)
+{
+	return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp);
+}
diff --git a/bin/dash/src/mystring.h b/bin/dash/src/mystring.h
new file mode 100644
index 00000000..083ea98c
--- /dev/null
+++ b/bin/dash/src/mystring.h
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)mystring.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <inttypes.h>
+#include <string.h>
+
+extern const char snlfmt[];
+extern const char spcstr[];
+extern const char dolatstr[];
+#define DOLATSTRLEN 6
+extern const char qchars[];
+extern const char illnum[];
+extern const char homestr[];
+
+#if 0
+void scopyn(const char *, char *, int);
+#endif
+char *prefix(const char *, const char *);
+void badnum(const char *s) __attribute__ ((noreturn));
+intmax_t atomax(const char *, int);
+intmax_t atomax10(const char *);
+int number(const char *);
+int is_number(const char *);
+char *single_quote(const char *);
+char *sstrdup(const char *);
+int pstrcmp(const void *, const void *);
+const char *const *findstring(const char *, const char *const *, size_t);
+
+#define equal(s1, s2)	(strcmp(s1, s2) == 0)
+#define scopy(s1, s2)	((void)strcpy(s2, s1))
diff --git a/bin/dash/src/nodes.c.pat b/bin/dash/src/nodes.c.pat
new file mode 100644
index 00000000..9125bc73
--- /dev/null
+++ b/bin/dash/src/nodes.c.pat
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)nodes.c.pat	8.2 (Berkeley) 5/4/95
+ */
+
+#include <stdlib.h>
+/*
+ * Routine for dealing with parsed shell commands.
+ */
+
+#include "shell.h"
+#include "nodes.h"
+#include "memalloc.h"
+#include "machdep.h"
+#include "mystring.h"
+#include "system.h"
+
+
+int     funcblocksize;		/* size of structures in function */
+int     funcstringsize;		/* size of strings in node */
+pointer funcblock;		/* block to allocate function from */
+char   *funcstring;		/* block to allocate strings from */
+
+%SIZES
+
+
+STATIC void calcsize(union node *);
+STATIC void sizenodelist(struct nodelist *);
+STATIC union node *copynode(union node *);
+STATIC struct nodelist *copynodelist(struct nodelist *);
+STATIC char *nodesavestr(char *);
+
+
+
+/*
+ * Make a copy of a parse tree.
+ */
+
+struct funcnode *
+copyfunc(union node *n)
+{
+	struct funcnode *f;
+	size_t blocksize;
+
+	funcblocksize = offsetof(struct funcnode, n);
+	funcstringsize = 0;
+	calcsize(n);
+	blocksize = funcblocksize;
+	f = ckmalloc(blocksize + funcstringsize);
+	funcblock = (char *) f + offsetof(struct funcnode, n);
+	funcstring = (char *) f + blocksize;
+	copynode(n);
+	f->count = 0;
+	return f;
+}
+
+
+
+STATIC void
+calcsize(n)
+	union node *n;
+{
+	%CALCSIZE
+}
+
+
+
+STATIC void
+sizenodelist(lp)
+	struct nodelist *lp;
+{
+	while (lp) {
+		funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
+		calcsize(lp->n);
+		lp = lp->next;
+	}
+}
+
+
+
+STATIC union node *
+copynode(n)
+	union node *n;
+{
+	union node *new;
+
+	%COPY
+	return new;
+}
+
+
+STATIC struct nodelist *
+copynodelist(lp)
+	struct nodelist *lp;
+{
+	struct nodelist *start;
+	struct nodelist **lpp;
+
+	lpp = &start;
+	while (lp) {
+		*lpp = funcblock;
+		funcblock = (char *) funcblock +
+		    SHELL_ALIGN(sizeof(struct nodelist));
+		(*lpp)->n = copynode(lp->n);
+		lp = lp->next;
+		lpp = &(*lpp)->next;
+	}
+	*lpp = NULL;
+	return start;
+}
+
+
+
+STATIC char *
+nodesavestr(s)
+	char   *s;
+{
+	char   *rtn = funcstring;
+
+	funcstring = stpcpy(funcstring, s) + 1;
+	return rtn;
+}
+
+
+
+/*
+ * Free a parse tree.
+ */
+
+void
+freefunc(struct funcnode *f)
+{
+	if (f && --f->count < 0)
+		ckfree(f);
+}
diff --git a/bin/dash/src/nodetypes b/bin/dash/src/nodetypes
new file mode 100644
index 00000000..ceaf478c
--- /dev/null
+++ b/bin/dash/src/nodetypes
@@ -0,0 +1,151 @@
+# Copyright (c) 1991, 1993
+#	The Regents of the University of California.  All rights reserved.
+# Copyright (c) 1997-2005
+#	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+#
+# This code is derived from software contributed to Berkeley by
+# Kenneth Almquist.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)nodetypes	8.2 (Berkeley) 5/4/95
+
+# This file describes the nodes used in parse trees.  Unindented lines
+# contain a node type followed by a structure tag.  Subsequent indented
+# lines specify the fields of the structure.  Several node types can share
+# the same structure, in which case the fields of the structure should be
+# specified only once.
+#
+# A field of a structure is described by the name of the field followed
+# by a type.  The currently implemented types are:
+#	nodeptr - a pointer to a node
+#	nodelist - a pointer to a list of nodes
+#	string - a pointer to a nul terminated string
+#	int - an integer
+#	other - any type that can be copied by assignment
+#	temp - a field that doesn't have to be copied when the node is copied
+# The last two types should be followed by the text of a C declaration for
+# the field.
+
+NCMD ncmd			# a simple command
+	type	  int
+	linno	  int
+	assign    nodeptr		# variable assignments
+	args	  nodeptr		# the arguments
+	redirect  nodeptr		# list of file redirections
+
+NPIPE npipe			# a pipeline
+	type	  int
+	backgnd	  int			# set to run pipeline in background
+	cmdlist	  nodelist		# the commands in the pipeline
+
+NREDIR nredir			# redirection (of a complex command)
+	type	  int
+	linno	  int
+	n	  nodeptr		# the command
+	redirect  nodeptr		# list of file redirections
+
+NBACKGND nredir			# run command in background
+NSUBSHELL nredir		# run command in a subshell
+
+NAND nbinary			# the && operator
+NOR nbinary			# the || operator
+
+NSEMI nbinary			# two commands separated by a semicolon
+	type	  int
+	ch1	  nodeptr		# the first child
+	ch2	  nodeptr		# the second child
+
+NIF nif				# the if statement.  Elif clauses are handled
+	type	  int		    # using multiple if nodes.
+	test	  nodeptr		# if test
+	ifpart	  nodeptr		# then ifpart
+	elsepart  nodeptr		# else elsepart
+
+NWHILE nbinary			# the while statement.  First child is the test
+NUNTIL nbinary			# the until statement
+
+NFOR nfor			# the for statement
+	type	  int
+	linno	  int
+	args	  nodeptr		# for var in args
+	body	  nodeptr		# do body; done
+	var	  string		# the for variable
+
+NCASE ncase			# a case statement
+	type	  int
+	linno	  int
+	expr	  nodeptr		# the word to switch on
+	cases	  nodeptr		# the list of cases (NCLIST nodes)
+
+NCLIST nclist			# a case
+	type	  int
+	next	  nodeptr		# the next case in list
+	pattern	  nodeptr		# list of patterns for this case
+	body	  nodeptr		# code to execute for this case
+
+
+NDEFUN ndefun			# a function
+	type	  int
+	linno	  int
+	text	  string
+	body	  nodeptr
+
+NARG narg			# represents a word
+	type	  int
+	next	  nodeptr		# next word in list
+	text	  string		# the text of the word
+	backquote nodelist		# list of commands in back quotes
+
+NTO nfile			# fd> fname
+NCLOBBER nfile			# fd>| fname
+NFROM nfile			# fd< fname
+NFROMTO nfile			# fd<> fname
+NAPPEND nfile			# fd>> fname
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	fname	  nodeptr		# file name, in a NARG node
+	expfname  temp	char *expfname	# actual file name
+
+NTOFD ndup			# fd<&dupfd
+NFROMFD ndup			# fd>&dupfd
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	dupfd	  int			# file descriptor to duplicate
+	vname	  nodeptr		# file name if fd>&$var
+
+
+NHERE nhere			# fd<<\!
+NXHERE nhere			# fd<<!
+	type	  int
+	next	  nodeptr		# next redirection in list
+	fd	  int			# file descriptor being redirected
+	doc	  nodeptr		# input to command (NARG node)
+
+NNOT nnot			# ! command  (actually pipeline)
+	type	int
+	com	nodeptr
diff --git a/bin/dash/src/options.c b/bin/dash/src/options.c
new file mode 100644
index 00000000..a46c23b9
--- /dev/null
+++ b/bin/dash/src/options.c
@@ -0,0 +1,558 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#define DEFINE_OPTIONS
+#include "options.h"
+#undef DEFINE_OPTIONS
+#include "nodes.h"	/* for other header files */
+#include "eval.h"
+#include "jobs.h"
+#include "input.h"
+#include "output.h"
+#include "trap.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+#include "show.h"
+
+char *arg0;			/* value of $0 */
+struct shparam shellparam;	/* current positional parameters */
+char **argptr;			/* argument list for builtin commands */
+char *optionarg;		/* set by nextopt (like getopt) */
+char *optptr;			/* used by nextopt */
+
+char *minusc;			/* argument to -c option */
+
+static const char *const optnames[NOPTS] = {
+	"errexit",
+	"noglob",
+	"ignoreeof",
+	"interactive",
+	"monitor",
+	"noexec",
+	"stdin",
+	"xtrace",
+	"verbose",
+	"vi",
+	"emacs",
+	"noclobber",
+	"allexport",
+	"notify",
+	"nounset",
+	"nolog",
+	"debug",
+};
+
+const char optletters[NOPTS] = {
+	'e',
+	'f',
+	'I',
+	'i',
+	'm',
+	'n',
+	's',
+	'x',
+	'v',
+	'V',
+	'E',
+	'C',
+	'a',
+	'b',
+	'u',
+	0,
+	0,
+};
+
+char optlist[NOPTS];
+
+
+static int options(int);
+STATIC void minus_o(char *, int);
+STATIC void setoption(int, int);
+STATIC int getopts(char *, char *, char **);
+
+
+/*
+ * Process the shell command line arguments.
+ */
+
+int
+procargs(int argc, char **argv)
+{
+	int i;
+	const char *xminusc;
+	char **xargv;
+	int login;
+
+	xargv = argv;
+	login = xargv[0] && xargv[0][0] == '-';
+	arg0 = xargv[0];
+	if (argc > 0)
+		xargv++;
+	for (i = 0; i < NOPTS; i++)
+		optlist[i] = 2;
+	argptr = xargv;
+	login |= options(1);
+	xargv = argptr;
+	xminusc = minusc;
+	if (*xargv == NULL) {
+		if (xminusc)
+			sh_error("-c requires an argument");
+		sflag = 1;
+	}
+	if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
+		iflag = 1;
+	if (mflag == 2)
+		mflag = iflag;
+	for (i = 0; i < NOPTS; i++)
+		if (optlist[i] == 2)
+			optlist[i] = 0;
+#if DEBUG == 2
+	debug = 1;
+#endif
+	/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
+	if (xminusc) {
+		minusc = *xargv++;
+		if (*xargv)
+			goto setarg0;
+	} else if (!sflag) {
+		setinputfile(*xargv, 0);
+setarg0:
+		arg0 = *xargv++;
+	}
+
+	shellparam.p = xargv;
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+	/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
+	while (*xargv) {
+		shellparam.nparam++;
+		xargv++;
+	}
+	optschanged();
+
+	return login;
+}
+
+
+void
+optschanged(void)
+{
+#ifdef DEBUG
+	opentrace();
+#endif
+	setinteractive(iflag);
+#ifndef SMALL
+	histedit();
+#endif
+	setjobctl(mflag);
+}
+
+/*
+ * Process shell options.  The global variable argptr contains a pointer
+ * to the argument list; we advance it past the options.
+ */
+
+STATIC int
+options(int cmdline)
+{
+	char *p;
+	int val;
+	int c;
+	int login = 0;
+
+	if (cmdline)
+		minusc = NULL;
+	while ((p = *argptr) != NULL) {
+		argptr++;
+		if ((c = *p++) == '-') {
+			val = 1;
+                        if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
+                                if (!cmdline) {
+                                        /* "-" means turn off -x and -v */
+                                        if (p[0] == '\0')
+                                                xflag = vflag = 0;
+                                        /* "--" means reset params */
+                                        else if (*argptr == NULL)
+						setparam(argptr);
+                                }
+				break;	  /* "-" or  "--" terminates options */
+			}
+		} else if (c == '+') {
+			val = 0;
+		} else {
+			argptr--;
+			break;
+		}
+		while ((c = *p++) != '\0') {
+			if (c == 'c' && cmdline) {
+				minusc = p;	/* command is after shell args*/
+			} else if (c == 'l' && cmdline) {
+				login = 1;
+			} else if (c == 'o') {
+				minus_o(*argptr, val);
+				if (*argptr)
+					argptr++;
+			} else {
+				setoption(c, val);
+			}
+		}
+	}
+
+	return login;
+}
+
+STATIC void
+minus_o(char *name, int val)
+{
+	int i;
+
+	if (name == NULL) {
+		if (val) {
+			out1str("Current option settings\n");
+			for (i = 0; i < NOPTS; i++)
+				out1fmt("%-16s%s\n", optnames[i],
+					optlist[i] ? "on" : "off");
+		} else {
+			for (i = 0; i < NOPTS; i++)
+				out1fmt("set %s %s\n",
+					optlist[i] ? "-o" : "+o",
+					optnames[i]);
+
+		}
+	} else {
+		for (i = 0; i < NOPTS; i++)
+			if (equal(name, optnames[i])) {
+				optlist[i] = val;
+				return;
+			}
+		sh_error("Illegal option -o %s", name);
+	}
+}
+
+
+STATIC void
+setoption(int flag, int val)
+{
+	int i;
+
+	for (i = 0; i < NOPTS; i++)
+		if (optletters[i] == flag) {
+			optlist[i] = val;
+			if (val) {
+				/* #%$ hack for ksh semantics */
+				if (flag == 'V')
+					Eflag = 0;
+				else if (flag == 'E')
+					Vflag = 0;
+			}
+			return;
+		}
+	sh_error("Illegal option -%c", flag);
+	/* NOTREACHED */
+}
+
+
+
+/*
+ * Set the shell parameters.
+ */
+
+void
+setparam(char **argv)
+{
+	char **newparam;
+	char **ap;
+	int nparam;
+
+	for (nparam = 0 ; argv[nparam] ; nparam++);
+	ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
+	while (*argv) {
+		*ap++ = savestr(*argv++);
+	}
+	*ap = NULL;
+	freeparam(&shellparam);
+	shellparam.malloc = 1;
+	shellparam.nparam = nparam;
+	shellparam.p = newparam;
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+}
+
+
+/*
+ * Free the list of positional parameters.
+ */
+
+void
+freeparam(volatile struct shparam *param)
+{
+	char **ap;
+
+	if (param->malloc) {
+		for (ap = param->p ; *ap ; ap++)
+			ckfree(*ap);
+		ckfree(param->p);
+	}
+}
+
+
+
+/*
+ * The shift builtin command.
+ */
+
+int
+shiftcmd(int argc, char **argv)
+{
+	int n;
+	char **ap1, **ap2;
+
+	n = 1;
+	if (argc > 1)
+		n = number(argv[1]);
+	if (n > shellparam.nparam)
+		sh_error("can't shift that many");
+	INTOFF;
+	shellparam.nparam -= n;
+	for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
+		if (shellparam.malloc)
+			ckfree(*ap1);
+	}
+	ap2 = shellparam.p;
+	while ((*ap2++ = *ap1++) != NULL);
+	shellparam.optind = 1;
+	shellparam.optoff = -1;
+	INTON;
+	return 0;
+}
+
+
+
+/*
+ * The set command builtin.
+ */
+
+int
+setcmd(int argc, char **argv)
+{
+	if (argc == 1)
+		return showvars(nullstr, 0, VUNSET);
+	INTOFF;
+	options(0);
+	optschanged();
+	if (*argptr != NULL) {
+		setparam(argptr);
+	}
+	INTON;
+	return 0;
+}
+
+
+void
+getoptsreset(value)
+	const char *value;
+{
+	shellparam.optind = number(value) ?: 1;
+	shellparam.optoff = -1;
+}
+
+/*
+ * The getopts builtin.  Shellparam.optnext points to the next argument
+ * to be processed.  Shellparam.optptr points to the next character to
+ * be processed in the current argument.  If shellparam.optnext is NULL,
+ * then it's the first time getopts has been called.
+ */
+
+int
+getoptscmd(int argc, char **argv)
+{
+	char **optbase;
+
+	if (argc < 3)
+		sh_error("Usage: getopts optstring var [arg]");
+	else if (argc == 3) {
+		optbase = shellparam.p;
+		if ((unsigned)shellparam.optind > shellparam.nparam + 1) {
+			shellparam.optind = 1;
+			shellparam.optoff = -1;
+		}
+	}
+	else {
+		optbase = &argv[3];
+		if ((unsigned)shellparam.optind > argc - 2) {
+			shellparam.optind = 1;
+			shellparam.optoff = -1;
+		}
+	}
+
+	return getopts(argv[1], argv[2], optbase);
+}
+
+STATIC int
+getopts(char *optstr, char *optvar, char **optfirst)
+{
+	char *p, *q;
+	char c = '?';
+	int done = 0;
+	char s[2];
+	char **optnext;
+	int ind = shellparam.optind;
+	int off = shellparam.optoff;
+
+	shellparam.optind = -1;
+	optnext = optfirst + ind - 1;
+
+	if (ind <= 1 || off < 0 || strlen(optnext[-1]) < off)
+		p = NULL;
+	else
+		p = optnext[-1] + off;
+	if (p == NULL || *p == '\0') {
+		/* Current word is done, advance */
+		p = *optnext;
+		if (p == NULL || *p != '-' || *++p == '\0') {
+atend:
+			p = NULL;
+			done = 1;
+			goto out;
+		}
+		optnext++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			goto atend;
+	}
+
+	c = *p++;
+	for (q = optstr; *q != c; ) {
+		if (*q == '\0') {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				setvar("OPTARG", s, 0);
+			} else {
+				outfmt(&errout, "Illegal option -%c\n", c);
+				(void) unsetvar("OPTARG");
+			}
+			c = '?';
+			goto out;
+		}
+		if (*++q == ':')
+			q++;
+	}
+
+	if (*++q == ':') {
+		if (*p == '\0' && (p = *optnext) == NULL) {
+			if (optstr[0] == ':') {
+				s[0] = c;
+				s[1] = '\0';
+				setvar("OPTARG", s, 0);
+				c = ':';
+			} else {
+				outfmt(&errout, "No arg for -%c option\n", c);
+				(void) unsetvar("OPTARG");
+				c = '?';
+			}
+			goto out;
+		}
+
+		if (p == *optnext)
+			optnext++;
+		setvar("OPTARG", p, 0);
+		p = NULL;
+	} else
+		setvar("OPTARG", nullstr, 0);
+
+out:
+	ind = optnext - optfirst + 1;
+	setvarint("OPTIND", ind, VNOFUNC);
+	s[0] = c;
+	s[1] = '\0';
+	setvar(optvar, s, 0);
+
+	shellparam.optoff = p ? p - *(optnext - 1) : -1;
+	shellparam.optind = ind;
+
+	return done;
+}
+
+/*
+ * XXX - should get rid of.  have all builtins use getopt(3).  the
+ * library getopt must have the BSD extension static variable "optreset"
+ * otherwise it can't be used within the shell safely.
+ *
+ * Standard option processing (a la getopt) for builtin routines.  The
+ * only argument that is passed to nextopt is the option string; the
+ * other arguments are unnecessary.  It return the character, or '\0' on
+ * end of input.
+ */
+
+int
+nextopt(const char *optstring)
+{
+	char *p;
+	const char *q;
+	char c;
+
+	if ((p = optptr) == NULL || *p == '\0') {
+		p = *argptr;
+		if (p == NULL || *p != '-' || *++p == '\0')
+			return '\0';
+		argptr++;
+		if (p[0] == '-' && p[1] == '\0')	/* check for "--" */
+			return '\0';
+	}
+	c = *p++;
+	for (q = optstring ; *q != c ; ) {
+		if (*q == '\0')
+			sh_error("Illegal option -%c", c);
+		if (*++q == ':')
+			q++;
+	}
+	if (*++q == ':') {
+		if (*p == '\0' && (p = *argptr++) == NULL)
+			sh_error("No arg for -%c option", c);
+		optionarg = p;
+		p = NULL;
+	}
+	optptr = p;
+	return c;
+}
diff --git a/bin/dash/src/options.h b/bin/dash/src/options.h
new file mode 100644
index 00000000..975fe339
--- /dev/null
+++ b/bin/dash/src/options.h
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)options.h	8.2 (Berkeley) 5/4/95
+ */
+
+struct shparam {
+	int nparam;		/* # of positional parameters (without $0) */
+	unsigned char malloc;	/* if parameter list dynamically allocated */
+	char **p;		/* parameter list */
+	int optind;		/* next parameter to be processed by getopts */
+	int optoff;		/* used by getopts */
+};
+
+
+
+#define eflag optlist[0]
+#define fflag optlist[1]
+#define Iflag optlist[2]
+#define iflag optlist[3]
+#define mflag optlist[4]
+#define nflag optlist[5]
+#define sflag optlist[6]
+#define xflag optlist[7]
+#define vflag optlist[8]
+#define Vflag optlist[9]
+#define	Eflag optlist[10]
+#define	Cflag optlist[11]
+#define	aflag optlist[12]
+#define	bflag optlist[13]
+#define	uflag optlist[14]
+#define	nolog optlist[15]
+#define	debug optlist[16]
+
+#define NOPTS	17
+
+extern const char optletters[NOPTS];
+extern char optlist[NOPTS];
+
+
+extern char *minusc;		/* argument to -c option */
+extern char *arg0;		/* $0 */
+extern struct shparam shellparam;  /* $@ */
+extern char **argptr;		/* argument list for builtin commands */
+extern char *optionarg;		/* set by nextopt */
+extern char *optptr;		/* used by nextopt */
+
+int procargs(int, char **);
+void optschanged(void);
+void setparam(char **);
+void freeparam(volatile struct shparam *);
+int shiftcmd(int, char **);
+int setcmd(int, char **);
+int getoptscmd(int, char **);
+int nextopt(const char *);
+void getoptsreset(const char *);
diff --git a/bin/dash/src/output.c b/bin/dash/src/output.c
new file mode 100644
index 00000000..e9ee9b4d
--- /dev/null
+++ b/bin/dash/src/output.c
@@ -0,0 +1,429 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+/*
+ * Shell output routines.  We use our own output routines because:
+ *	When a builtin command is interrupted we have to discard
+ *		any pending output.
+ *	When a builtin command appears in back quotes, we want to
+ *		save the output of the command in a region obtained
+ *		via malloc, rather than doing a fork and reading the
+ *		output of the command via a pipe.
+ *	Our output routines may be smaller than the stdio routines.
+ */
+
+#include <sys/types.h>		/* quad_t */
+#include <sys/param.h>		/* BSD4_4 */
+#include <sys/ioctl.h>
+
+#include <stdio.h>	/* defines BUFSIZ */
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef USE_GLIBC_STDIO
+#include <fcntl.h>
+#endif
+#include <limits.h>
+
+#include "shell.h"
+#include "syntax.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "main.h"
+#include "system.h"
+
+
+#define OUTBUFSIZ BUFSIZ
+#define MEM_OUT -3		/* output to dynamically allocated memory */
+
+
+#ifdef USE_GLIBC_STDIO
+struct output output = {
+	.stream = 0, .nextc = 0, .end = 0, .buf = 0, .bufsize = 0, .fd = 1, .flags = 0
+};
+struct output errout = {
+	.stream = 0, .nextc = 0, .end = 0, .buf = 0, .bufsize = 0, .fd = 2, .flags = 0
+}
+#ifdef notyet
+struct output memout = {
+	.stream = 0, .nextc = 0, .end = 0, .buf = 0, .bufsize = 0, .fd = MEM_OUT, .flags = 0
+};
+#endif
+#else
+struct output output = {
+	.nextc = 0, .end = 0, .buf = 0, .bufsize = OUTBUFSIZ, .fd = 1, .flags = 0
+};
+struct output errout = {
+	.nextc = 0, .end = 0, .buf = 0, .bufsize = 0, .fd = 2, .flags = 0
+};
+struct output preverrout;
+#ifdef notyet
+struct output memout = {
+	.nextc = 0, .end = 0, .buf = 0, .bufsize = 0, .fd = MEM_OUT, .flags = 0
+};
+#endif
+#endif
+struct output *out1 = &output;
+struct output *out2 = &errout;
+
+
+static int xvsnprintf(char *, size_t, const char *, va_list);
+
+
+#ifdef mkinit
+
+INCLUDE "output.h"
+INCLUDE "memalloc.h"
+
+INIT {
+#ifdef USE_GLIBC_STDIO
+	initstreams();
+#endif
+}
+
+RESET {
+#ifdef notyet
+	out1 = &output;
+	out2 = &errout;
+#ifdef USE_GLIBC_STDIO
+	if (memout.stream != NULL)
+		__closememout();
+#endif
+	if (memout.buf != NULL) {
+		ckfree(memout.buf);
+		memout.buf = NULL;
+	}
+#endif
+}
+
+#endif
+
+
+void
+outmem(const char *p, size_t len, struct output *dest)
+{
+#ifdef USE_GLIBC_STDIO
+	INTOFF;
+	fwrite(p, 1, len, dest->stream);
+	INTON;
+#else
+	size_t bufsize;
+	size_t offset;
+	size_t nleft;
+
+	nleft = dest->end - dest->nextc;
+	if (likely(nleft >= len)) {
+buffered:
+		dest->nextc = mempcpy(dest->nextc, p, len);
+		return;
+	}
+
+	bufsize = dest->bufsize;
+	if (!bufsize) {
+		;
+	} else if (dest->buf == NULL) {
+#ifdef notyet
+		if (dest->fd == MEM_OUT && len > bufsize) {
+			bufsize = len;
+		}
+#endif
+		offset = 0;
+#ifdef notyet
+		goto alloc;
+	} else if (dest->fd == MEM_OUT) {
+		offset = bufsize;
+		if (bufsize >= len) {
+			bufsize <<= 1;
+		} else {
+			bufsize += len;
+		}
+		if (bufsize < offset)
+			goto err;
+alloc:
+#endif
+		INTOFF;
+		dest->buf = ckrealloc(dest->buf, bufsize);
+		dest->bufsize = bufsize;
+		dest->end = dest->buf + bufsize;
+		dest->nextc = dest->buf + offset;
+		INTON;
+	} else {
+		flushout(dest);
+	}
+
+	nleft = dest->end - dest->nextc;
+	if (nleft > len)
+		goto buffered;
+
+	if ((xwrite(dest->fd, p, len))) {
+#ifdef notyet
+err:
+#endif
+		dest->flags |= OUTPUT_ERR;
+	}
+#endif
+}
+
+
+void
+outstr(const char *p, struct output *file)
+{
+#ifdef USE_GLIBC_STDIO
+	INTOFF;
+	fputs(p, file->stream);
+	INTON;
+#else
+	size_t len;
+
+	len = strlen(p);
+	outmem(p, len, file);
+#endif
+}
+
+
+#ifndef USE_GLIBC_STDIO
+
+
+void
+outcslow(int c, struct output *dest)
+{
+	char buf = c;
+	outmem(&buf, 1, dest);
+}
+#endif
+
+
+void
+flushall(void)
+{
+	flushout(&output);
+#ifdef FLUSHERR
+	flushout(&errout);
+#endif
+}
+
+
+void
+flushout(struct output *dest)
+{
+#ifdef USE_GLIBC_STDIO
+	INTOFF;
+	fflush(dest->stream);
+	INTON;
+#else
+	size_t len;
+
+	len = dest->nextc - dest->buf;
+	if (!len || dest->fd < 0)
+		return;
+	dest->nextc = dest->buf;
+	if ((xwrite(dest->fd, dest->buf, len)))
+		dest->flags |= OUTPUT_ERR;
+#endif
+}
+
+
+void
+outfmt(struct output *file, const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(file, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+out1fmt(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	doformat(out1, fmt, ap);
+	va_end(ap);
+}
+
+
+int
+fmtstr(char *outbuf, size_t length, const char *fmt, ...)
+{
+	va_list ap;
+	int ret;
+
+	va_start(ap, fmt);
+	ret = xvsnprintf(outbuf, length, fmt, ap);
+	va_end(ap);
+	return ret > (int)length ? length : ret;
+}
+
+
+static int xvasprintf(char **sp, size_t size, const char *f, va_list ap)
+{
+	char *s;
+	int len;
+	va_list ap2;
+
+	va_copy(ap2, ap);
+	len = xvsnprintf(*sp, size, f, ap2);
+	va_end(ap2);
+	if (len < 0)
+		sh_error("xvsnprintf failed");
+	if (len < size)
+		return len;
+
+	s = stalloc((len >= stackblocksize() ? len : stackblocksize()) + 1);
+	*sp = s;
+	len = xvsnprintf(s, len + 1, f, ap);
+	return len;
+}
+
+
+int xasprintf(char **sp, const char *f, ...)
+{
+	va_list ap;
+	int ret;
+
+	va_start(ap, f);
+	ret = xvasprintf(sp, 0, f, ap);
+	va_end(ap);
+	return ret;
+}
+
+
+#ifndef USE_GLIBC_STDIO
+void
+doformat(struct output *dest, const char *f, va_list ap)
+{
+	struct stackmark smark;
+	char *s;
+	int len;
+	int olen;
+
+	setstackmark(&smark);
+	s = dest->nextc;
+	olen = dest->end - dest->nextc;
+	len = xvasprintf(&s, olen, f, ap);
+	if (likely(olen > len)) {
+		dest->nextc += len;
+		goto out;
+	}
+	outmem(s, len, dest);
+out:
+	popstackmark(&smark);
+}
+#endif
+
+
+
+/*
+ * Version of write which resumes after a signal is caught.
+ */
+
+int
+xwrite(int fd, const void *p, size_t n)
+{
+	const char *buf = p;
+
+	while (n) {
+		ssize_t i;
+		size_t m;
+
+		m = n;
+		if (m > SSIZE_MAX)
+			m = SSIZE_MAX;
+		do {
+			i = write(fd, buf, m);
+		} while (i < 0 && errno == EINTR);
+		if (i < 0)
+			return -1;
+		buf += i;
+		n -= i;
+	}
+	return 0;
+}
+
+
+#ifdef notyet
+#ifdef USE_GLIBC_STDIO
+void initstreams() {
+	output.stream = stdout;
+	errout.stream = stderr;
+}
+
+
+void
+openmemout(void) {
+	INTOFF;
+	memout.stream = open_memstream(&memout.buf, &memout.bufsize);
+	INTON;
+}
+
+
+int
+__closememout(void) {
+	int error;
+	error = fclose(memout.stream);
+	memout.stream = NULL;
+	return error;
+}
+#endif
+#endif
+
+
+static int
+xvsnprintf(char *outbuf, size_t length, const char *fmt, va_list ap)
+{
+	int ret;
+
+#ifdef __sun
+	/*
+	 * vsnprintf() on older versions of Solaris returns -1 when
+	 * passed a length of 0.  To avoid this, use a dummy
+	 * 1-character buffer instead.
+	 */
+	char dummy[1];
+
+	if (length == 0) {
+		outbuf = dummy;
+		length = sizeof(dummy);
+	}
+#endif
+
+	INTOFF;
+	ret = vsnprintf(outbuf, length, fmt, ap);
+	INTON;
+	return ret;
+}
diff --git a/bin/dash/src/output.h b/bin/dash/src/output.h
new file mode 100644
index 00000000..c43d4937
--- /dev/null
+++ b/bin/dash/src/output.h
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)output.h	8.2 (Berkeley) 5/4/95
+ */
+
+#ifndef OUTPUT_INCL
+
+#include <stdarg.h>
+#ifdef USE_GLIBC_STDIO
+#include <stdio.h>
+#endif
+#include <sys/types.h>
+
+struct output {
+#ifdef USE_GLIBC_STDIO
+	FILE *stream;
+#endif
+	char *nextc;
+	char *end;
+	char *buf;
+	size_t bufsize;
+	int fd;
+	int flags;
+};
+
+extern struct output output;
+extern struct output errout;
+extern struct output preverrout;
+#ifdef notyet
+extern struct output memout;
+#endif
+extern struct output *out1;
+extern struct output *out2;
+
+void outmem(const char *, size_t, struct output *);
+void outstr(const char *, struct output *);
+#ifndef USE_GLIBC_STDIO
+void outcslow(int, struct output *);
+#endif
+void flushall(void);
+void flushout(struct output *);
+void outfmt(struct output *, const char *, ...)
+    __attribute__((__format__(__printf__,2,3)));
+void out1fmt(const char *, ...)
+    __attribute__((__format__(__printf__,1,2)));
+int fmtstr(char *, size_t, const char *, ...)
+    __attribute__((__format__(__printf__,3,4)));
+int xasprintf(char **, const char *, ...);
+#ifndef USE_GLIBC_STDIO
+void doformat(struct output *, const char *, va_list);
+#endif
+int xwrite(int, const void *, size_t);
+#ifdef notyet
+#ifdef USE_GLIBC_STDIO
+void initstreams(void);
+void openmemout(void);
+int __closememout(void);
+#endif
+#endif
+
+static inline void
+freestdout()
+{
+	output.nextc = output.buf;
+	output.flags = 0;
+}
+
+#define OUTPUT_ERR 01		/* error occurred on output */
+
+#ifdef USE_GLIBC_STDIO
+static inline void outc(int ch, struct output *file)
+{
+	putc(ch, file->stream);
+}
+#define doformat(d, f, a)	vfprintf((d)->stream, (f), (a))
+#else
+static inline void outc(int ch, struct output *file)
+{
+	if (file->nextc == file->end)
+		outcslow(ch, file);
+	else {
+		*file->nextc = ch;
+		file->nextc++;
+	}
+}
+#endif
+#define out1c(c)	outc((c), out1)
+#define out2c(c)	outcslow((c), out2)
+#define out1mem(s, l)	outmem((s), (l), out1)
+#define out1str(s)	outstr((s), out1)
+#define out2str(s)	outstr((s), out2)
+#define outerr(f)	(f)->flags
+
+#define OUTPUT_INCL
+#endif
diff --git a/bin/dash/src/parser.c b/bin/dash/src/parser.c
new file mode 100644
index 00000000..499f7f8e
--- /dev/null
+++ b/bin/dash/src/parser.c
@@ -0,0 +1,1677 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include <stdlib.h>
+
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "expand.h"	/* defines rmescapes() */
+#include "exec.h"	/* defines find_builtin() */
+#include "syntax.h"
+#include "options.h"
+#include "input.h"
+#include "output.h"
+#include "var.h"
+#include "error.h"
+#include "memalloc.h"
+#include "mystring.h"
+#include "alias.h"
+#include "show.h"
+#include "builtins.h"
+#include "system.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+
+/*
+ * Shell command parser.
+ */
+
+/* values returned by readtoken */
+#include "token_vars.h"
+
+
+
+/* Used by expandstr to get here-doc like behaviour. */
+#define FAKEEOFMARK (char *)1
+
+
+
+struct heredoc {
+	struct heredoc *next;	/* next here document in list */
+	union node *here;		/* redirection node */
+	char *eofmark;		/* string indicating end of input */
+	int striptabs;		/* if set, strip leading tabs */
+};
+
+struct synstack {
+	const char *syntax;
+	struct synstack *prev;
+	struct synstack *next;
+	int innerdq;
+	int varpushed;
+	int dblquote;
+	int varnest;		/* levels of variables expansion */
+	int parenlevel;		/* levels of parens in arithmetic */
+	int dqvarnest;		/* levels of variables expansion within double quotes */
+};
+
+
+
+struct heredoc *heredoclist;	/* list of here documents to read */
+int doprompt;			/* if set, prompt the user */
+int needprompt;			/* true if interactive and at start of line */
+int lasttoken;			/* last token read */
+int tokpushback;		/* last token pushed back */
+char *wordtext;			/* text of last word returned by readtoken */
+int checkkwd;
+struct nodelist *backquotelist;
+union node *redirnode;
+struct heredoc *heredoc;
+int quoteflag;			/* set if (part of) last token was quoted */
+
+
+static char *promptcache;
+static char *rpromptcache;
+
+
+STATIC union node *list(int);
+STATIC union node *andor(void);
+STATIC union node *pipeline(void);
+STATIC union node *command(void);
+STATIC union node *simplecmd(void);
+STATIC union node *makename(void);
+STATIC void parsefname(void);
+STATIC void parseheredoc(void);
+STATIC int readtoken(void);
+STATIC int xxreadtoken(void);
+STATIC int pgetc_eatbnl();
+STATIC int readtoken1(int, char const *, char *, int);
+STATIC void synexpect(int) __attribute__((__noreturn__));
+STATIC void synerror(const char *) __attribute__((__noreturn__));
+STATIC void setprompt(int);
+
+
+int isassignment(const char *p)
+{
+	const char *q = endofname(p);
+	if (p == q)
+		return 0;
+	return *q == '=';
+}
+
+static inline int realeofmark(const char *eofmark)
+{
+	return eofmark && eofmark != FAKEEOFMARK;
+}
+
+
+/*
+ * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
+ * valid parse tree indicating a blank line.)
+ */
+
+union node *
+parsecmd(int interact)
+{
+	tokpushback = 0;
+	checkkwd = 0;
+	heredoclist = 0;
+	doprompt = interact;
+	if (doprompt)
+		setprompt(doprompt);
+	needprompt = 0;
+	return list(1);
+}
+
+
+STATIC union node *
+list(int nlflag)
+{
+	int chknl = nlflag & 1 ? 0 : CHKNL;
+	union node *n1, *n2, *n3;
+	int tok;
+
+	n1 = NULL;
+	for (;;) {
+		checkkwd = chknl | CHKKWD | CHKALIAS;
+		tok = readtoken();
+		switch (tok) {
+		case TNL:
+			parseheredoc();
+			return n1;
+
+		case TEOF:
+			if (!n1 && !chknl)
+				n1 = NEOF;
+out_eof:
+			parseheredoc();
+			tokpushback++;
+			lasttoken = TEOF;
+			return n1;
+		}
+
+		tokpushback++;
+		if (nlflag == 2 && tokendlist[tok])
+			return n1;
+		nlflag |= 2;
+
+		n2 = andor();
+		tok = readtoken();
+		if (tok == TBACKGND) {
+			if (n2->type == NPIPE) {
+				n2->npipe.backgnd = 1;
+			} else {
+				if (n2->type != NREDIR) {
+					n3 = stalloc(sizeof(struct nredir));
+					n3->nredir.n = n2;
+					n3->nredir.redirect = NULL;
+					n2 = n3;
+				}
+				n2->type = NBACKGND;
+			}
+		}
+		if (n1 == NULL) {
+			n1 = n2;
+		}
+		else {
+			n3 = (union node *)stalloc(sizeof (struct nbinary));
+			n3->type = NSEMI;
+			n3->nbinary.ch1 = n1;
+			n3->nbinary.ch2 = n2;
+			n1 = n3;
+		}
+		switch (tok) {
+		case TEOF:
+			goto out_eof;
+		case TNL:
+			tokpushback++;
+			/* fall through */
+		case TBACKGND:
+		case TSEMI:
+			break;
+		default:
+			if (!chknl)
+				synexpect(-1);
+			tokpushback++;
+			return n1;
+		}
+	}
+}
+
+
+
+STATIC union node *
+andor(void)
+{
+	union node *n1, *n2, *n3;
+	int t;
+
+	n1 = pipeline();
+	for (;;) {
+		if ((t = readtoken()) == TAND) {
+			t = NAND;
+		} else if (t == TOR) {
+			t = NOR;
+		} else {
+			tokpushback++;
+			return n1;
+		}
+		checkkwd = CHKNL | CHKKWD | CHKALIAS;
+		n2 = pipeline();
+		n3 = (union node *)stalloc(sizeof (struct nbinary));
+		n3->type = t;
+		n3->nbinary.ch1 = n1;
+		n3->nbinary.ch2 = n2;
+		n1 = n3;
+	}
+}
+
+
+
+STATIC union node *
+pipeline(void)
+{
+	union node *n1, *n2, *pipenode;
+	struct nodelist *lp, *prev;
+	int negate;
+
+	negate = 0;
+	TRACE(("pipeline: entered\n"));
+	if (readtoken() == TNOT) {
+		negate = !negate;
+		checkkwd = CHKKWD | CHKALIAS;
+	} else
+		tokpushback++;
+	n1 = command();
+	if (readtoken() == TPIPE) {
+		pipenode = (union node *)stalloc(sizeof (struct npipe));
+		pipenode->type = NPIPE;
+		pipenode->npipe.backgnd = 0;
+		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+		pipenode->npipe.cmdlist = lp;
+		lp->n = n1;
+		do {
+			prev = lp;
+			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+			checkkwd = CHKNL | CHKKWD | CHKALIAS;
+			lp->n = command();
+			prev->next = lp;
+		} while (readtoken() == TPIPE);
+		lp->next = NULL;
+		n1 = pipenode;
+	}
+	tokpushback++;
+	if (negate) {
+		n2 = (union node *)stalloc(sizeof (struct nnot));
+		n2->type = NNOT;
+		n2->nnot.com = n1;
+		return n2;
+	} else
+		return n1;
+}
+
+
+
+STATIC union node *
+command(void)
+{
+	union node *n1, *n2;
+	union node *ap, **app;
+	union node *cp, **cpp;
+	union node *redir, **rpp;
+	union node **rpp2;
+	int t;
+	int savelinno;
+
+	redir = NULL;
+	rpp2 = &redir;
+
+	savelinno = plinno;
+
+	switch (readtoken()) {
+	default:
+		synexpect(-1);
+		/* NOTREACHED */
+	case TIF:
+		n1 = (union node *)stalloc(sizeof (struct nif));
+		n1->type = NIF;
+		n1->nif.test = list(0);
+		if (readtoken() != TTHEN)
+			synexpect(TTHEN);
+		n1->nif.ifpart = list(0);
+		n2 = n1;
+		while (readtoken() == TELIF) {
+			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
+			n2 = n2->nif.elsepart;
+			n2->type = NIF;
+			n2->nif.test = list(0);
+			if (readtoken() != TTHEN)
+				synexpect(TTHEN);
+			n2->nif.ifpart = list(0);
+		}
+		if (lasttoken == TELSE)
+			n2->nif.elsepart = list(0);
+		else {
+			n2->nif.elsepart = NULL;
+			tokpushback++;
+		}
+		t = TFI;
+		break;
+	case TWHILE:
+	case TUNTIL: {
+		int got;
+		n1 = (union node *)stalloc(sizeof (struct nbinary));
+		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
+		n1->nbinary.ch1 = list(0);
+		if ((got=readtoken()) != TDO) {
+TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
+			synexpect(TDO);
+		}
+		n1->nbinary.ch2 = list(0);
+		t = TDONE;
+		break;
+	}
+	case TFOR:
+		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
+			synerror("Bad for loop variable");
+		n1 = (union node *)stalloc(sizeof (struct nfor));
+		n1->type = NFOR;
+		n1->nfor.linno = savelinno;
+		n1->nfor.var = wordtext;
+		checkkwd = CHKNL | CHKKWD | CHKALIAS;
+		if (readtoken() == TIN) {
+			app = &ap;
+			while (readtoken() == TWORD) {
+				n2 = (union node *)stalloc(sizeof (struct narg));
+				n2->type = NARG;
+				n2->narg.text = wordtext;
+				n2->narg.backquote = backquotelist;
+				*app = n2;
+				app = &n2->narg.next;
+			}
+			*app = NULL;
+			n1->nfor.args = ap;
+			if (lasttoken != TNL && lasttoken != TSEMI)
+				synexpect(-1);
+		} else {
+			n2 = (union node *)stalloc(sizeof (struct narg));
+			n2->type = NARG;
+			n2->narg.text = (char *)dolatstr;
+			n2->narg.backquote = NULL;
+			n2->narg.next = NULL;
+			n1->nfor.args = n2;
+			/*
+			 * Newline or semicolon here is optional (but note
+			 * that the original Bourne shell only allowed NL).
+			 */
+			if (lasttoken != TSEMI)
+				tokpushback++;
+		}
+		checkkwd = CHKNL | CHKKWD | CHKALIAS;
+		if (readtoken() != TDO)
+			synexpect(TDO);
+		n1->nfor.body = list(0);
+		t = TDONE;
+		break;
+	case TCASE:
+		n1 = (union node *)stalloc(sizeof (struct ncase));
+		n1->type = NCASE;
+		n1->ncase.linno = savelinno;
+		if (readtoken() != TWORD)
+			synexpect(TWORD);
+		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
+		n2->type = NARG;
+		n2->narg.text = wordtext;
+		n2->narg.backquote = backquotelist;
+		n2->narg.next = NULL;
+		checkkwd = CHKNL | CHKKWD | CHKALIAS;
+		if (readtoken() != TIN)
+			synexpect(TIN);
+		cpp = &n1->ncase.cases;
+next_case:
+		checkkwd = CHKNL | CHKKWD;
+		t = readtoken();
+		while(t != TESAC) {
+			if (lasttoken == TLP)
+				readtoken();
+			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
+			cp->type = NCLIST;
+			app = &cp->nclist.pattern;
+			for (;;) {
+				*app = ap = (union node *)stalloc(sizeof (struct narg));
+				ap->type = NARG;
+				ap->narg.text = wordtext;
+				ap->narg.backquote = backquotelist;
+				if (readtoken() != TPIPE)
+					break;
+				app = &ap->narg.next;
+				readtoken();
+			}
+			ap->narg.next = NULL;
+			if (lasttoken != TRP)
+				synexpect(TRP);
+			cp->nclist.body = list(2);
+
+			cpp = &cp->nclist.next;
+
+			checkkwd = CHKNL | CHKKWD;
+			if ((t = readtoken()) != TESAC) {
+				if (t != TENDCASE)
+					synexpect(TENDCASE);
+				else
+					goto next_case;
+			}
+		}
+		*cpp = NULL;
+		goto redir;
+	case TLP:
+		n1 = (union node *)stalloc(sizeof (struct nredir));
+		n1->type = NSUBSHELL;
+		n1->nredir.linno = savelinno;
+		n1->nredir.n = list(0);
+		n1->nredir.redirect = NULL;
+		t = TRP;
+		break;
+	case TBEGIN:
+		n1 = list(0);
+		t = TEND;
+		break;
+	case TWORD:
+	case TREDIR:
+		tokpushback++;
+		return simplecmd();
+	}
+
+	if (readtoken() != t)
+		synexpect(t);
+
+redir:
+	/* Now check for redirection which may follow command */
+	checkkwd = CHKKWD | CHKALIAS;
+	rpp = rpp2;
+	while (readtoken() == TREDIR) {
+		*rpp = n2 = redirnode;
+		rpp = &n2->nfile.next;
+		parsefname();
+	}
+	tokpushback++;
+	*rpp = NULL;
+	if (redir) {
+		if (n1->type != NSUBSHELL) {
+			n2 = (union node *)stalloc(sizeof (struct nredir));
+			n2->type = NREDIR;
+			n2->nredir.linno = savelinno;
+			n2->nredir.n = n1;
+			n1 = n2;
+		}
+		n1->nredir.redirect = redir;
+	}
+
+	return n1;
+}
+
+
+STATIC union node *
+simplecmd(void) {
+	union node *args, **app;
+	union node *n = NULL;
+	union node *vars, **vpp;
+	union node **rpp, *redir;
+	int savecheckkwd;
+	int savelinno;
+
+	args = NULL;
+	app = &args;
+	vars = NULL;
+	vpp = &vars;
+	redir = NULL;
+	rpp = &redir;
+
+	savecheckkwd = CHKALIAS;
+	savelinno = plinno;
+	for (;;) {
+		checkkwd = savecheckkwd;
+		switch (readtoken()) {
+		case TWORD:
+			n = (union node *)stalloc(sizeof (struct narg));
+			n->type = NARG;
+			n->narg.text = wordtext;
+			n->narg.backquote = backquotelist;
+			if (savecheckkwd && isassignment(wordtext)) {
+				*vpp = n;
+				vpp = &n->narg.next;
+			} else {
+				*app = n;
+				app = &n->narg.next;
+				savecheckkwd = 0;
+			}
+			break;
+		case TREDIR:
+			*rpp = n = redirnode;
+			rpp = &n->nfile.next;
+			parsefname();	/* read name of redirection file */
+			break;
+		case TLP:
+			if (
+				args && app == &args->narg.next &&
+				!vars && !redir
+			) {
+				struct builtincmd *bcmd;
+				const char *name;
+
+				/* We have a function */
+				if (readtoken() != TRP)
+					synexpect(TRP);
+				name = n->narg.text;
+				if (
+					!goodname(name) || (
+						(bcmd = find_builtin(name)) &&
+						bcmd->flags & BUILTIN_SPECIAL
+					)
+				)
+					synerror("Bad function name");
+				n->type = NDEFUN;
+				checkkwd = CHKNL | CHKKWD | CHKALIAS;
+				n->ndefun.text = n->narg.text;
+				n->ndefun.linno = plinno;
+				n->ndefun.body = command();
+				return n;
+			}
+			/* fall through */
+		default:
+			tokpushback++;
+			goto out;
+		}
+	}
+out:
+	*app = NULL;
+	*vpp = NULL;
+	*rpp = NULL;
+	n = (union node *)stalloc(sizeof (struct ncmd));
+	n->type = NCMD;
+	n->ncmd.linno = savelinno;
+	n->ncmd.args = args;
+	n->ncmd.assign = vars;
+	n->ncmd.redirect = redir;
+	return n;
+}
+
+STATIC union node *
+makename(void)
+{
+	union node *n;
+
+	n = (union node *)stalloc(sizeof (struct narg));
+	n->type = NARG;
+	n->narg.next = NULL;
+	n->narg.text = wordtext;
+	n->narg.backquote = backquotelist;
+	return n;
+}
+
+void fixredir(union node *n, const char *text, int err)
+	{
+	TRACE(("Fix redir %s %d\n", text, err));
+	if (!err)
+		n->ndup.vname = NULL;
+
+	if (is_digit(text[0]) && text[1] == '\0')
+		n->ndup.dupfd = digit_val(text[0]);
+	else if (text[0] == '-' && text[1] == '\0')
+		n->ndup.dupfd = -1;
+	else {
+
+		if (err)
+			synerror("Bad fd number");
+		else
+			n->ndup.vname = makename();
+	}
+}
+
+
+STATIC void
+parsefname(void)
+{
+	union node *n = redirnode;
+
+	if (n->type == NHERE)
+		checkkwd = CHKEOFMARK;
+	if (readtoken() != TWORD)
+		synexpect(-1);
+	if (n->type == NHERE) {
+		struct heredoc *here = heredoc;
+		struct heredoc *p;
+
+		if (quoteflag == 0)
+			n->type = NXHERE;
+		TRACE(("Here document %d\n", n->type));
+		rmescapes(wordtext);
+		here->eofmark = wordtext;
+		here->next = NULL;
+		if (heredoclist == NULL)
+			heredoclist = here;
+		else {
+			for (p = heredoclist ; p->next ; p = p->next);
+			p->next = here;
+		}
+	} else if (n->type == NTOFD || n->type == NFROMFD) {
+		fixredir(n, wordtext, 0);
+	} else {
+		n->nfile.fname = makename();
+	}
+}
+
+
+/*
+ * Input any here documents.
+ */
+
+STATIC void
+parseheredoc(void)
+{
+	struct heredoc *here;
+	union node *n;
+
+	here = heredoclist;
+	heredoclist = 0;
+
+	while (here) {
+		if (needprompt) {
+			setprompt(2);
+		}
+		if (here->here->type == NHERE)
+			readtoken1(pgetc(), SQSYNTAX, here->eofmark, here->striptabs);
+		else
+			readtoken1(pgetc_eatbnl(), DQSYNTAX, here->eofmark, here->striptabs);
+		n = (union node *)stalloc(sizeof (struct narg));
+		n->narg.type = NARG;
+		n->narg.next = NULL;
+		n->narg.text = wordtext;
+		n->narg.backquote = backquotelist;
+		here->here->nhere.doc = n;
+		here = here->next;
+	}
+}
+
+STATIC int
+readtoken(void)
+{
+	int t;
+	int kwd = checkkwd;
+#ifdef DEBUG
+	int alreadyseen = tokpushback;
+#endif
+
+top:
+	t = xxreadtoken();
+
+	/*
+	 * eat newlines
+	 */
+	if (kwd & CHKNL) {
+		while (t == TNL) {
+			parseheredoc();
+			checkkwd = 0;
+			t = xxreadtoken();
+		}
+	}
+
+	kwd |= checkkwd;
+	checkkwd = 0;
+
+	if (t != TWORD || quoteflag) {
+		goto out;
+	}
+
+	/*
+	 * check for keywords
+	 */
+	if (kwd & CHKKWD) {
+		const char *const *pp;
+
+		if ((pp = findkwd(wordtext))) {
+			lasttoken = t = pp - parsekwd + KWDOFFSET;
+			TRACE(("keyword %s recognized\n", tokname[t]));
+			goto out;
+		}
+	}
+
+	if (kwd & CHKALIAS) {
+		struct alias *ap;
+		if ((ap = lookupalias(wordtext, 1)) != NULL) {
+			if (*ap->val) {
+				pushstring(ap->val, ap);
+			}
+			goto top;
+		}
+	}
+out:
+#ifdef DEBUG
+	if (!alreadyseen)
+	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
+	else
+	    TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
+#endif
+	return (t);
+}
+
+static void nlprompt(void)
+{
+	plinno++;
+	if (doprompt)
+		setprompt(2);
+}
+
+static void nlnoprompt(void)
+{
+	plinno++;
+	needprompt = doprompt;
+}
+
+
+/*
+ * Read the next input token.
+ * If the token is a word, we set backquotelist to the list of cmds in
+ *	backquotes.  We set quoteflag to true if any part of the word was
+ *	quoted.
+ * If the token is TREDIR, then we set redirnode to a structure containing
+ *	the redirection.
+ *
+ * [Change comment:  here documents and internal procedures]
+ * [Readtoken shouldn't have any arguments.  Perhaps we should make the
+ *  word parsing code into a separate routine.  In this case, readtoken
+ *  doesn't need to have any internal procedures, but parseword does.
+ *  We could also make parseoperator in essence the main routine, and
+ *  have parseword (readtoken1?) handle both words and redirection.]
+ */
+
+#define RETURN(token)	return lasttoken = token
+
+STATIC int
+xxreadtoken(void)
+{
+	int c;
+
+	if (tokpushback) {
+		tokpushback = 0;
+		return lasttoken;
+	}
+	if (needprompt) {
+		setprompt(2);
+	}
+	for (;;) {	/* until token or start of word found */
+		c = pgetc_eatbnl();
+		switch (c) {
+		case ' ': case '\t':
+		case PEOA:
+			continue;
+		case '#':
+			while ((c = pgetc()) != '\n' && c != PEOF);
+			pungetc();
+			continue;
+		case '\n':
+			nlnoprompt();
+			RETURN(TNL);
+		case PEOF:
+			RETURN(TEOF);
+		case '&':
+			if (pgetc_eatbnl() == '&')
+				RETURN(TAND);
+			pungetc();
+			RETURN(TBACKGND);
+		case '|':
+			if (pgetc_eatbnl() == '|')
+				RETURN(TOR);
+			pungetc();
+			RETURN(TPIPE);
+		case ';':
+			if (pgetc_eatbnl() == ';')
+				RETURN(TENDCASE);
+			pungetc();
+			RETURN(TSEMI);
+		case '(':
+			RETURN(TLP);
+		case ')':
+			RETURN(TRP);
+		}
+		break;
+	}
+	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
+#undef RETURN
+}
+
+static int pgetc_eatbnl(void)
+{
+	int c;
+
+	while ((c = pgetc()) == '\\') {
+		if (pgetc2() != '\n') {
+			pungetc();
+			break;
+		}
+
+		nlprompt();
+	}
+
+	return c;
+}
+
+static int pgetc_top(struct synstack *stack)
+{
+	return stack->syntax == SQSYNTAX ? pgetc() : pgetc_eatbnl();
+}
+
+static void synstack_push(struct synstack **stack, struct synstack *next,
+			  const char *syntax)
+{
+	memset(next, 0, sizeof(*next));
+	next->syntax = syntax;
+	next->next = *stack;
+	(*stack)->prev = next;
+	*stack = next;
+}
+
+static void synstack_pop(struct synstack **stack)
+{
+	*stack = (*stack)->next;
+}
+
+
+
+/*
+ * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
+ * is not NULL, read a here document.  In the latter case, eofmark is the
+ * word which marks the end of the document and striptabs is true if
+ * leading tabs should be stripped from the document.  The argument firstc
+ * is the first character of the input token or document.
+ *
+ * Because C does not have internal subroutines, I have simulated them
+ * using goto's to implement the subroutine linkage.  The following macros
+ * will run code that appears at the end of readtoken1.
+ */
+
+#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)
+{
+	int c = firstc;
+	char *out;
+	size_t len;
+	struct nodelist *bqlist;
+	int quotef;
+	int oldstyle;
+	/* syntax stack */
+	struct synstack synbase = { .syntax = syntax };
+	struct synstack *synstack = &synbase;
+
+	if (syntax == DQSYNTAX)
+		synstack->dblquote = 1;
+	quotef = 0;
+	bqlist = NULL;
+
+	STARTSTACKSTR(out);
+	loop: {	/* for each line, until end of word */
+#if ATTY
+		if (c == '\034' && doprompt
+		 && attyset() && ! equal(termval(), "emacs")) {
+			attyline();
+			if (synstack->syntax == BASESYNTAX)
+				return readtoken();
+			c = pgetc_top(synstack);
+			goto loop;
+		}
+#endif
+		CHECKEND();	/* set c to PEOF if at end of here document */
+		for (;;) {	/* until end of line or end of word */
+			CHECKSTRSPACE(4, out);	/* permit 4 calls to USTPUTC */
+			switch(synstack->syntax[c]) {
+			case CNL:	/* '\n' */
+				if (synstack->syntax == BASESYNTAX &&
+				    !synstack->varnest)
+					goto endword;	/* exit outer loop */
+				USTPUTC(c, out);
+				nlprompt();
+				c = pgetc_top(synstack);
+				goto loop;		/* continue outer loop */
+			case CWORD:
+				USTPUTC(c, out);
+				break;
+			case CCTL:
+				if ((!eofmark) | synstack->dblquote |
+				    synstack->varnest)
+					USTPUTC(CTLESC, out);
+				USTPUTC(c, out);
+				break;
+			/* backslash */
+			case CBACK:
+				c = pgetc2();
+				if (c == PEOF) {
+					USTPUTC(CTLESC, out);
+					USTPUTC('\\', out);
+					pungetc();
+				} else {
+					if (
+						synstack->dblquote &&
+						c != '\\' && c != '`' &&
+						c != '$' && (
+							c != '"' ||
+							(eofmark != NULL &&
+							 !synstack->varnest)
+						) && (
+							c != '}' ||
+							!synstack->varnest
+						)
+					) {
+						USTPUTC(CTLESC, out);
+						USTPUTC('\\', out);
+					}
+					USTPUTC(CTLESC, out);
+					USTPUTC(c, out);
+					quotef++;
+				}
+				break;
+			case CSQUOTE:
+				synstack->syntax = SQSYNTAX;
+quotemark:
+				if (eofmark == NULL) {
+					USTPUTC(CTLQUOTEMARK, out);
+				}
+				break;
+			case CDQUOTE:
+				synstack->syntax = DQSYNTAX;
+				synstack->dblquote = 1;
+toggledq:
+				if (synstack->varnest)
+					synstack->innerdq ^= 1;
+				goto quotemark;
+			case CENDQUOTE:
+				if (eofmark && !synstack->varnest) {
+					USTPUTC(c, out);
+					break;
+				}
+
+				if (synstack->dqvarnest == 0) {
+					synstack->syntax = BASESYNTAX;
+					synstack->dblquote = 0;
+				}
+
+				quotef++;
+
+				if (c == '"')
+					goto toggledq;
+
+				goto quotemark;
+			case CVAR:	/* '$' */
+				PARSESUB();		/* parse substitution */
+				break;
+			case CENDVAR:	/* '}' */
+				if (!synstack->innerdq &&
+				    synstack->varnest > 0) {
+					if (!--synstack->varnest &&
+					    synstack->varpushed)
+						synstack_pop(&synstack);
+					else if (synstack->dqvarnest > 0)
+						synstack->dqvarnest--;
+					USTPUTC(CTLENDVAR, out);
+				} else {
+					USTPUTC(c, out);
+				}
+				break;
+			case CLP:	/* '(' in arithmetic */
+				synstack->parenlevel++;
+				USTPUTC(c, out);
+				break;
+			case CRP:	/* ')' in arithmetic */
+				if (synstack->parenlevel > 0) {
+					USTPUTC(c, out);
+					--synstack->parenlevel;
+				} else {
+					if (pgetc_eatbnl() == ')') {
+						USTPUTC(CTLENDARI, out);
+						synstack_pop(&synstack);
+					} else {
+						/*
+						 * unbalanced parens
+						 *  (don't 2nd guess - no error)
+						 */
+						pungetc();
+						USTPUTC(')', out);
+					}
+				}
+				break;
+			case CBQUOTE:	/* '`' */
+				if (checkkwd & CHKEOFMARK) {
+					USTPUTC('`', out);
+					break;
+				}
+
+				PARSEBACKQOLD();
+				break;
+			case CEOF:
+				goto endword;		/* exit outer loop */
+			case CIGN:
+				break;
+			default:
+				if (synstack->varnest == 0)
+					goto endword;	/* exit outer loop */
+				if (c != PEOA) {
+					USTPUTC(c, out);
+				}
+			}
+			c = pgetc_top(synstack);
+		}
+	}
+endword:
+	if (synstack->syntax == ARISYNTAX)
+		synerror("Missing '))'");
+	if (synstack->syntax != BASESYNTAX && eofmark == NULL)
+		synerror("Unterminated quoted string");
+	if (synstack->varnest != 0) {
+		/* { */
+		synerror("Missing '}'");
+	}
+	USTPUTC('\0', out);
+	len = out - (char *)stackblock();
+	out = stackblock();
+	if (eofmark == NULL) {
+		if ((c == '>' || c == '<')
+		 && quotef == 0
+		 && len <= 2
+		 && (*out == '\0' || is_digit(*out))) {
+			PARSEREDIR();
+			return lasttoken = TREDIR;
+		} else {
+			pungetc();
+		}
+	}
+	quoteflag = quotef;
+	backquotelist = bqlist;
+	grabstackblock(len);
+	wordtext = out;
+	return lasttoken = TWORD;
+/* 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
+ * we are at the end of the here document, this routine sets the c to PEOF.
+ */
+
+checkend: {
+	if (realeofmark(eofmark)) {
+		int markloc;
+		char *p;
+
+		if (c == PEOA) {
+			c = pgetc2();
+		}
+		if (striptabs) {
+			while (c == '\t') {
+				c = pgetc2();
+			}
+		}
+
+		markloc = out - (char *)stackblock();
+		for (p = eofmark; STPUTC(c, out), *p; p++) {
+			if (c != *p)
+				goto more_heredoc;
+
+			c = pgetc2();
+		}
+
+		if (c == '\n' || c == PEOF) {
+			c = PEOF;
+			nlnoprompt();
+		} else {
+			int len;
+
+more_heredoc:
+			p = (char *)stackblock() + markloc + 1;
+			len = out - p;
+
+			if (len) {
+				len -= c < 0;
+				c = p[-1];
+
+				if (len) {
+					char *str;
+
+					str = alloca(len + 1);
+					*(char *)mempcpy(str, p, len) = 0;
+
+					pushstring(str, NULL);
+				}
+			}
+		}
+
+		STADJUST((char *)stackblock() + markloc - out, out);
+	}
+	goto checkend_return;
+}
+
+
+/*
+ * Parse a redirection operator.  The variable "out" points to a string
+ * specifying the fd to be redirected.  The variable "c" contains the
+ * first character of the redirection operator.
+ */
+
+parseredir: {
+	char fd = *out;
+	union node *np;
+
+	np = (union node *)stalloc(sizeof (struct nfile));
+	if (c == '>') {
+		np->nfile.fd = 1;
+		c = pgetc_eatbnl();
+		if (c == '>')
+			np->type = NAPPEND;
+		else if (c == '|')
+			np->type = NCLOBBER;
+		else if (c == '&')
+			np->type = NTOFD;
+		else {
+			np->type = NTO;
+			pungetc();
+		}
+	} else {	/* c == '<' */
+		np->nfile.fd = 0;
+		switch (c = pgetc_eatbnl()) {
+		case '<':
+			if (sizeof (struct nfile) != sizeof (struct nhere)) {
+				np = (union node *)stalloc(sizeof (struct nhere));
+				np->nfile.fd = 0;
+			}
+			np->type = NHERE;
+			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
+			heredoc->here = np;
+			if ((c = pgetc_eatbnl()) == '-') {
+				heredoc->striptabs = 1;
+			} else {
+				heredoc->striptabs = 0;
+				pungetc();
+			}
+			break;
+
+		case '&':
+			np->type = NFROMFD;
+			break;
+
+		case '>':
+			np->type = NFROMTO;
+			break;
+
+		default:
+			np->type = NFROM;
+			pungetc();
+			break;
+		}
+	}
+	if (fd != '\0')
+		np->nfile.fd = digit_val(fd);
+	redirnode = np;
+	goto parseredir_return;
+}
+
+
+/*
+ * Parse a substitution.  At this point, we have read the dollar sign
+ * and nothing else.
+ */
+
+parsesub: {
+	int subtype;
+	int typeloc;
+	char *p;
+	static const char types[] = "}-+?=";
+
+	c = pgetc_eatbnl();
+	if (
+		(checkkwd & CHKEOFMARK) ||
+		c <= PEOA  ||
+		(c != '(' && c != '{' && !is_name(c) && !is_special(c))
+	) {
+		USTPUTC('$', out);
+		pungetc();
+	} else if (c == '(') {	/* $(command) or $((arith)) */
+		if (pgetc_eatbnl() == '(') {
+			PARSEARITH();
+		} else {
+			pungetc();
+			PARSEBACKQNEW();
+		}
+	} else {
+		const char *newsyn = synstack->syntax;
+
+		USTPUTC(CTLVAR, out);
+		typeloc = out - (char *)stackblock();
+		STADJUST(1, out);
+		subtype = VSNORMAL;
+		if (likely(c == '{')) {
+			c = pgetc_eatbnl();
+			subtype = 0;
+		}
+varname:
+		if (is_name(c)) {
+			do {
+				STPUTC(c, out);
+				c = pgetc_eatbnl();
+			} while (is_in_name(c));
+		} else if (is_digit(c)) {
+			do {
+				STPUTC(c, out);
+				c = pgetc_eatbnl();
+			} while (!subtype && is_digit(c));
+		} else if (c != '}') {
+			int cc = c;
+
+			c = pgetc_eatbnl();
+
+			if (!subtype && cc == '#') {
+				subtype = VSLENGTH;
+
+				if (c == '_' || isalnum(c))
+					goto varname;
+
+				cc = c;
+				c = pgetc_eatbnl();
+				if (cc == '}' || c != '}') {
+					pungetc();
+					subtype = 0;
+					c = cc;
+					cc = '#';
+				}
+			}
+
+			if (!is_special(cc)) {
+				if (subtype == VSLENGTH)
+					subtype = 0;
+				goto badsub;
+			}
+
+			USTPUTC(cc, out);
+		} else
+			goto badsub;
+
+		if (subtype == 0) {
+			int cc = c;
+
+			switch (c) {
+			case ':':
+				subtype = VSNUL;
+				c = pgetc_eatbnl();
+				/*FALLTHROUGH*/
+			default:
+				p = strchr(types, c);
+				if (p == NULL)
+					break;
+				subtype |= p - types + VSNORMAL;
+				break;
+			case '%':
+			case '#':
+				subtype = c == '#' ? VSTRIMLEFT :
+						     VSTRIMRIGHT;
+				c = pgetc_eatbnl();
+				if (c == cc)
+					subtype++;
+				else
+					pungetc();
+
+				newsyn = BASESYNTAX;
+				break;
+			}
+		} else {
+badsub:
+			pungetc();
+		}
+
+		if (newsyn == ARISYNTAX)
+			newsyn = DQSYNTAX;
+
+		if ((newsyn != synstack->syntax || synstack->innerdq) &&
+		    subtype != VSNORMAL) {
+			synstack_push(&synstack,
+				      synstack->prev ?:
+				      alloca(sizeof(*synstack)),
+				      newsyn);
+
+			synstack->varpushed++;
+			synstack->dblquote = newsyn != BASESYNTAX;
+		}
+
+		*((char *)stackblock() + typeloc) = subtype;
+		if (subtype != VSNORMAL) {
+			synstack->varnest++;
+			if (synstack->dblquote)
+				synstack->dqvarnest++;
+		}
+		STPUTC('=', out);
+	}
+	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;
+	union node *n;
+	char *str;
+	size_t savelen;
+	struct heredoc *saveheredoclist;
+	int uninitialized_var(saveprompt);
+
+	str = NULL;
+	savelen = out - (char *)stackblock();
+	if (savelen > 0) {
+		str = alloca(savelen);
+		memcpy(str, stackblock(), savelen);
+	}
+        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 *pout;
+                int pc;
+                size_t psavelen;
+                char *pstr;
+
+
+                STARTSTACKSTR(pout);
+		for (;;) {
+			if (needprompt) {
+				setprompt(2);
+			}
+			switch (pc = pgetc_eatbnl()) {
+			case '`':
+				goto done;
+
+			case '\\':
+                                pc = pgetc();
+                                if (pc != '\\' && pc != '`' && pc != '$'
+                                    && (!synstack->dblquote || pc != '"'))
+                                        STPUTC('\\', pout);
+				if (pc > PEOA) {
+					break;
+				}
+				/* fall through */
+
+			case PEOF:
+			case PEOA:
+				synerror("EOF in backquote substitution");
+
+			case '\n':
+				nlnoprompt();
+				break;
+
+			default:
+				break;
+			}
+			STPUTC(pc, pout);
+                }
+done:
+                STPUTC('\0', pout);
+                psavelen = pout - (char *)stackblock();
+                if (psavelen > 0) {
+			pstr = grabstackstr(pout);
+			setinputstring(pstr);
+                }
+        }
+	nlpp = &bqlist;
+	while (*nlpp)
+		nlpp = &(*nlpp)->next;
+	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
+	(*nlpp)->next = NULL;
+
+	saveheredoclist = heredoclist;
+	heredoclist = NULL;
+
+	if (oldstyle) {
+		saveprompt = doprompt;
+		doprompt = 0;
+	}
+
+	n = list(2);
+
+	if (oldstyle)
+		doprompt = saveprompt;
+	else {
+		if (readtoken() != TRP)
+			synexpect(TRP);
+		setinputstring(nullstr);
+	}
+
+	parseheredoc();
+	heredoclist = saveheredoclist;
+
+	(*nlpp)->n = n;
+	/* Start reading from old file again. */
+	popfile();
+	/* Ignore any pushed back tokens left from the backquote parsing. */
+	if (oldstyle)
+		tokpushback = 0;
+	out = growstackto(savelen + 1);
+	if (str) {
+		memcpy(out, str, savelen);
+		STADJUST(savelen, out);
+	}
+	USTPUTC(CTLBACKQ, out);
+	if (oldstyle)
+		goto parsebackq_oldreturn;
+	else
+		goto parsebackq_newreturn;
+}
+
+/*
+ * Parse an arithmetic expansion (indicate start of one and set state)
+ */
+parsearith: {
+
+	synstack_push(&synstack,
+		      synstack->prev ?: alloca(sizeof(*synstack)),
+		      ARISYNTAX);
+	synstack->dblquote = 1;
+	USTPUTC(CTLARI, out);
+	goto parsearith_return;
+}
+
+} /* end of readtoken */
+
+
+
+#ifdef mkinit
+INCLUDE "parser.h"
+#endif
+
+
+/*
+ * Return of a legal variable name (a letter or underscore followed by zero or
+ * more letters, underscores, and digits).
+ */
+
+char *
+endofname(const char *name)
+	{
+	char *p;
+
+	p = (char *) name;
+	if (! is_name(*p))
+		return p;
+	while (*++p) {
+		if (! is_in_name(*p))
+			break;
+	}
+	return p;
+}
+
+
+/*
+ * Called when an unexpected token is read during the parse.  The argument
+ * is the token that is expected, or -1 if more than one type of token can
+ * occur at this point.
+ */
+
+STATIC void
+synexpect(int token)
+{
+	char msg[64];
+
+	if (token >= 0) {
+		fmtstr(msg, 64, "%s unexpected (expecting %s)",
+			tokname[lasttoken], tokname[token]);
+	} else {
+		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
+	}
+	synerror(msg);
+	/* NOTREACHED */
+}
+
+
+STATIC void
+synerror(const char *msg)
+{
+	errlinno = plinno;
+	sh_error("Syntax error: %s", msg);
+	/* NOTREACHED */
+}
+
+const char *
+expandstr(const char *ps)
+{
+	struct parsefile *file_stop;
+	struct jmploc *volatile savehandler;
+	struct heredoc *saveheredoclist;
+	const char *result;
+	int saveprompt;
+	struct jmploc jmploc;
+	union node n;
+	int err;
+
+	file_stop = parsefile;
+
+	/* XXX Fix (char *) cast. */
+	setinputstring((char *)ps);
+
+	saveheredoclist = heredoclist;
+	heredoclist = NULL;
+	saveprompt = doprompt;
+	doprompt = 0;
+	result = ps;
+	savehandler = handler;
+	if (unlikely(err = setjmp(jmploc.loc)))
+		goto out;
+	handler = &jmploc;
+
+	readtoken1(pgetc_eatbnl(), DQSYNTAX, FAKEEOFMARK, 0);
+
+	n.narg.type = NARG;
+	n.narg.next = NULL;
+	n.narg.text = wordtext;
+	n.narg.backquote = backquotelist;
+
+	expandarg(&n, NULL, EXP_QUOTED);
+	result = stackblock();
+
+out:
+	handler = savehandler;
+	if (err && exception != EXERROR)
+		longjmp(handler->loc, 1);
+
+	doprompt = saveprompt;
+	unwindfiles(file_stop);
+	heredoclist = saveheredoclist;
+
+	return result;
+}
+
+STATIC void
+setprompt(int which)
+{
+	struct stackmark smark;
+	const char *prompt, *rprompt, *nl;
+	int show;
+
+	needprompt = 0;
+	whichprompt = which;
+
+	switch (whichprompt) {
+	default:
+#ifdef DEBUG
+		prompt = "<internal prompt error>";
+		rprompt = prompt;
+		break;
+#endif
+	case 0:
+		prompt = nullstr;
+		rprompt = nullstr;
+		break;
+	case 1:
+		prompt = ps1val();
+		rprompt = rps1val();
+		break;
+	case 2:
+		prompt = ps2val();
+		rprompt = rps2val();
+		break;
+	}
+
+#ifdef SMALL
+	show = 1;
+#else
+	show = !el;
+#endif
+	pushstackmark(&smark, stackblocksize());
+	if (show) {
+		out2str(expandstr(prompt));
+	} else {
+		free(promptcache);
+		free(rpromptcache);
+		promptcache = savestr(expandstr(prompt));
+		rpromptcache = savestr(expandstr(rprompt));
+
+		nl = strrchr(promptcache, '\n');
+		if (nl)
+			outmem(promptcache, &nl[1] - promptcache, out2);
+	}
+	popstackmark(&smark);
+}
+
+/*
+ * called by editline -- return the cached prompt expansion.
+ */
+const char *
+getprompt(void *unused)
+{
+	const char *nl;
+
+	nl = strrchr(promptcache, '\n');
+
+	if (nl)
+		return &nl[1];
+	else
+		return promptcache;
+}
+
+const char *
+getrprompt(void *unused)
+{
+	return rpromptcache;
+}
+
+const char *const *
+findkwd(const char *s)
+{
+	return findstring(
+		s, parsekwd, sizeof(parsekwd) / sizeof(const char *)
+	);
+}
diff --git a/bin/dash/src/parser.h b/bin/dash/src/parser.h
new file mode 100644
index 00000000..6597faa8
--- /dev/null
+++ b/bin/dash/src/parser.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)parser.h	8.3 (Berkeley) 5/4/95
+ */
+
+#include "token.h"
+
+/* control characters in argument strings */
+#define CTL_FIRST -127		/* first 'special' character */
+#define CTLESC -127		/* escape next character */
+#define CTLVAR -126		/* variable defn */
+#define CTLENDVAR -125
+#define CTLBACKQ -124
+#define	CTLARI -122		/* arithmetic expression */
+#define	CTLENDARI -121
+#define	CTLQUOTEMARK -120
+#define	CTL_LAST -120		/* last 'special' character */
+
+/* variable substitution byte (follows CTLVAR) */
+#define VSTYPE	0x0f		/* type of variable substitution */
+#define VSNUL	0x10		/* colon--treat the empty string as unset */
+
+/* values of VSTYPE field */
+#define VSNORMAL	0x1		/* normal variable:  $var or ${var} */
+#define VSMINUS		0x2		/* ${var-text} */
+#define VSPLUS		0x3		/* ${var+text} */
+#define VSQUESTION	0x4		/* ${var?message} */
+#define VSASSIGN	0x5		/* ${var=text} */
+#define VSTRIMRIGHT	0x6		/* ${var%pattern} */
+#define VSTRIMRIGHTMAX 	0x7		/* ${var%%pattern} */
+#define VSTRIMLEFT	0x8		/* ${var#pattern} */
+#define VSTRIMLEFTMAX	0x9		/* ${var##pattern} */
+#define VSLENGTH	0xa		/* ${#var} */
+
+/* values of checkkwd variable */
+#define CHKALIAS	0x1
+#define CHKKWD		0x2
+#define CHKNL		0x4
+#define CHKEOFMARK	0x8
+
+
+/*
+ * NEOF is returned by parsecmd when it encounters an end of file.  It
+ * must be distinct from NULL, so we use the address of a variable that
+ * happens to be handy.
+ */
+extern int lasttoken;
+extern int tokpushback;
+#define NEOF ((union node *)&tokpushback)
+extern int whichprompt;		/* 1 == PS1, 2 == PS2 */
+extern int checkkwd;
+
+
+int isassignment(const char *p);
+union node *parsecmd(int);
+void fixredir(union node *, const char *, int);
+const char *getprompt(void *);
+const char *getrprompt(void *);
+const char *const *findkwd(const char *);
+char *endofname(const char *);
+const char *expandstr(const char *);
+
+static inline int
+goodname(const char *p)
+{
+	return !*endofname(p);
+}
+
+static inline int parser_eof(void)
+{
+	return tokpushback && lasttoken == TEOF;
+}
diff --git a/bin/dash/src/redir.c b/bin/dash/src/redir.c
new file mode 100644
index 00000000..895140c3
--- /dev/null
+++ b/bin/dash/src/redir.c
@@ -0,0 +1,483 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/param.h>	/* PIPE_BUF */
+#include <signal.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+/*
+ * Code for dealing with input/output redirection.
+ */
+
+#include "main.h"
+#include "shell.h"
+#include "nodes.h"
+#include "jobs.h"
+#include "options.h"
+#include "expand.h"
+#include "redir.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+
+
+#define EMPTY -2		/* marks an unused slot in redirtab */
+#define CLOSED -1		/* fd opened for redir needs to be closed */
+
+#ifndef PIPE_BUF
+# define PIPESIZE 4096		/* amount of buffering in a pipe */
+#else
+# define PIPESIZE PIPE_BUF
+#endif
+
+
+MKINIT
+struct redirtab {
+	struct redirtab *next;
+	int renamed[10];
+};
+
+
+MKINIT struct redirtab *redirlist;
+
+/* Bit map of currently closed file descriptors. */
+static unsigned closed_redirs;
+
+STATIC int openredirect(union node *);
+#ifdef notyet
+STATIC void dupredirect(union node *, int, char[10]);
+#else
+STATIC void dupredirect(union node *, int);
+#endif
+STATIC int openhere(union node *);
+
+
+static unsigned update_closed_redirs(int fd, int nfd)
+{
+	unsigned val = closed_redirs;
+	unsigned bit = 1 << fd;
+
+	if (nfd >= 0)
+		closed_redirs &= ~bit;
+	else
+		closed_redirs |= bit;
+
+	return val & bit;
+}
+
+
+/*
+ * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
+ * old file descriptors are stashed away so that the redirection can be
+ * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
+ * standard output, and the standard error if it becomes a duplicate of
+ * stdout, is saved in memory.
+ */
+
+void
+redirect(union node *redir, int flags)
+{
+	union node *n;
+	struct redirtab *sv;
+	int i;
+	int fd;
+	int newfd;
+	int *p;
+#if notyet
+	char memory[10];	/* file descriptors to write to memory */
+
+	for (i = 10 ; --i >= 0 ; )
+		memory[i] = 0;
+	memory[1] = flags & REDIR_BACKQ;
+#endif
+	if (!redir)
+		return;
+	sv = NULL;
+	INTOFF;
+	if (likely(flags & REDIR_PUSH))
+		sv = redirlist;
+	n = redir;
+	do {
+		newfd = openredirect(n);
+		if (newfd < -1)
+			continue;
+
+		fd = n->nfile.fd;
+
+		if (sv) {
+			int closed;
+
+			p = &sv->renamed[fd];
+			i = *p;
+
+			closed = update_closed_redirs(fd, newfd);
+
+			if (likely(i == EMPTY)) {
+				i = CLOSED;
+				if (fd != newfd && !closed) {
+					i = savefd(fd, fd);
+					fd = -1;
+				}
+			}
+
+			*p = i;
+		}
+
+		if (fd == newfd)
+			continue;
+
+#ifdef notyet
+		dupredirect(n, newfd, memory);
+#else
+		dupredirect(n, newfd);
+#endif
+	} while ((n = n->nfile.next));
+	INTON;
+#ifdef notyet
+	if (memory[1])
+		out1 = &memout;
+	if (memory[2])
+		out2 = &memout;
+#endif
+	if (flags & REDIR_SAVEFD2 && sv->renamed[2] >= 0)
+		preverrout.fd = sv->renamed[2];
+}
+
+
+STATIC int
+openredirect(union node *redir)
+{
+	struct stat64 sb;
+	char *fname;
+	int f;
+
+	switch (redir->nfile.type) {
+	case NFROM:
+		fname = redir->nfile.expfname;
+		if ((f = open64(fname, O_RDONLY)) < 0)
+			goto eopen;
+		break;
+	case NFROMTO:
+		fname = redir->nfile.expfname;
+		if ((f = open64(fname, O_RDWR|O_CREAT, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NTO:
+		/* Take care of noclobber mode. */
+		if (Cflag) {
+			fname = redir->nfile.expfname;
+			if (stat64(fname, &sb) < 0) {
+				if ((f = open64(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0)
+					goto ecreate;
+			} else if (!S_ISREG(sb.st_mode)) {
+				if ((f = open64(fname, O_WRONLY, 0666)) < 0)
+					goto ecreate;
+				if (!fstat64(f, &sb) && S_ISREG(sb.st_mode)) {
+					close(f);
+					errno = EEXIST;
+					goto ecreate;
+				}
+			} else {
+				errno = EEXIST;
+				goto ecreate;
+			}
+			break;
+		}
+		/* FALLTHROUGH */
+	case NCLOBBER:
+		fname = redir->nfile.expfname;
+		if ((f = open64(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NAPPEND:
+		fname = redir->nfile.expfname;
+		if ((f = open64(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
+			goto ecreate;
+		break;
+	case NTOFD:
+	case NFROMFD:
+		f = redir->ndup.dupfd;
+		if (f == redir->nfile.fd)
+			f = -2;
+		break;
+	default:
+#ifdef DEBUG
+		abort();
+#endif
+		/* Fall through to eliminate warning. */
+	case NHERE:
+	case NXHERE:
+		f = openhere(redir);
+		break;
+	}
+
+	return f;
+ecreate:
+	sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
+eopen:
+	sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
+}
+
+
+STATIC void
+#ifdef notyet
+dupredirect(redir, f, memory)
+#else
+dupredirect(redir, f)
+#endif
+	union node *redir;
+	int f;
+#ifdef notyet
+	char memory[10];
+#endif
+	{
+	int fd = redir->nfile.fd;
+	int err = 0;
+
+#ifdef notyet
+	memory[fd] = 0;
+#endif
+	if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
+		/* if not ">&-" */
+		if (f >= 0) {
+#ifdef notyet
+			if (memory[f])
+				memory[fd] = 1;
+			else
+#endif
+				if (dup2(f, fd) < 0) {
+					err = errno;
+					goto err;
+				}
+			return;
+		}
+		f = fd;
+	} else if (dup2(f, fd) < 0)
+		err = errno;
+
+	close(f);
+	if (err < 0)
+		goto err;
+
+	return;
+
+err:
+	sh_error("%d: %s", f, strerror(err));
+}
+
+
+/*
+ * Handle here documents.  Normally we fork off a process to write the
+ * data to a pipe.  If the document is short, we can stuff the data in
+ * the pipe without forking.
+ */
+
+STATIC int
+openhere(union node *redir)
+{
+	char *p;
+	int pip[2];
+	size_t len = 0;
+
+	if (pipe(pip) < 0)
+		sh_error("Pipe call failed");
+
+	p = redir->nhere.doc->narg.text;
+	if (redir->type == NXHERE) {
+		expandarg(redir->nhere.doc, NULL, EXP_QUOTED);
+		p = stackblock();
+	}
+
+	len = strlen(p);
+	if (len <= PIPESIZE) {
+		xwrite(pip[1], p, len);
+		goto out;
+	}
+
+	if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
+		close(pip[0]);
+		signal(SIGINT, SIG_IGN);
+		signal(SIGQUIT, SIG_IGN);
+		signal(SIGHUP, SIG_IGN);
+#ifdef SIGTSTP
+		signal(SIGTSTP, SIG_IGN);
+#endif
+		signal(SIGPIPE, SIG_DFL);
+		xwrite(pip[1], p, len);
+		_exit(0);
+	}
+out:
+	close(pip[1]);
+	return pip[0];
+}
+
+
+
+/*
+ * Undo the effects of the last redirection.
+ */
+
+void
+popredir(int drop)
+{
+	struct redirtab *rp;
+	int i;
+
+	INTOFF;
+	rp = redirlist;
+	for (i = 0 ; i < 10 ; i++) {
+		int closed;
+
+		if (rp->renamed[i] == EMPTY)
+			continue;
+
+		closed = drop ? 1 : update_closed_redirs(i, rp->renamed[i]);
+
+		switch (rp->renamed[i]) {
+		case CLOSED:
+			if (!closed)
+				close(i);
+			break;
+		default:
+			if (!drop)
+				dup2(rp->renamed[i], i);
+			close(rp->renamed[i]);
+			break;
+		}
+	}
+	redirlist = rp->next;
+	ckfree(rp);
+	INTON;
+}
+
+/*
+ * Undo all redirections.  Called on error or interrupt.
+ */
+
+#ifdef mkinit
+
+INCLUDE "redir.h"
+
+EXITRESET {
+	/*
+	 * Discard all saved file descriptors.
+	 */
+	unwindredir(0);
+}
+
+FORKRESET {
+	redirlist = NULL;
+}
+
+#endif
+
+
+
+/*
+ * Move a file descriptor to > 10.  Invokes sh_error on error unless
+ * the original file dscriptor is not open.
+ */
+
+int
+savefd(int from, int ofd)
+{
+	int newfd;
+	int err;
+
+	newfd = fcntl(from, F_DUPFD, 10);
+	err = newfd < 0 ? errno : 0;
+	if (err != EBADF) {
+		close(ofd);
+		if (err)
+			sh_error("%d: %s", from, strerror(err));
+		else
+			fcntl(newfd, F_SETFD, FD_CLOEXEC);
+	}
+
+	return newfd;
+}
+
+
+int
+redirectsafe(union node *redir, int flags)
+{
+	int err;
+	volatile int saveint;
+	struct jmploc *volatile savehandler = handler;
+	struct jmploc jmploc;
+
+	SAVEINT(saveint);
+	if (!(err = setjmp(jmploc.loc) * 2)) {
+		handler = &jmploc;
+		redirect(redir, flags);
+	}
+	handler = savehandler;
+	if (err && exception != EXERROR)
+		longjmp(handler->loc, 1);
+	RESTOREINT(saveint);
+	return err;
+}
+
+
+void unwindredir(struct redirtab *stop)
+{
+	while (redirlist != stop)
+		popredir(0);
+}
+
+
+struct redirtab *pushredir(union node *redir)
+{
+	struct redirtab *sv;
+	struct redirtab *q;
+	int i;
+
+	q = redirlist;
+	if (!redir)
+		goto out;
+
+	sv = ckmalloc(sizeof (struct redirtab));
+	sv->next = q;
+	redirlist = sv;
+	for (i = 0; i < 10; i++)
+		sv->renamed[i] = EMPTY;
+
+out:
+	return q;
+}
diff --git a/bin/dash/src/redir.h b/bin/dash/src/redir.h
new file mode 100644
index 00000000..1cf27616
--- /dev/null
+++ b/bin/dash/src/redir.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)redir.h	8.2 (Berkeley) 5/4/95
+ */
+
+/* flags passed to redirect */
+#define REDIR_PUSH 01		/* save previous values of file descriptors */
+#ifdef notyet
+#define REDIR_BACKQ 02		/* save the command output in memory */
+#endif
+#define REDIR_SAVEFD2 03	/* set preverrout */
+
+struct redirtab;
+union node;
+void redirect(union node *, int);
+void popredir(int);
+int savefd(int, int);
+int redirectsafe(union node *, int);
+void unwindredir(struct redirtab *stop);
+struct redirtab *pushredir(union node *redir);
+
diff --git a/bin/dash/src/shell.h b/bin/dash/src/shell.h
new file mode 100644
index 00000000..98edc8be
--- /dev/null
+++ b/bin/dash/src/shell.h
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)shell.h	8.2 (Berkeley) 5/4/95
+ */
+
+/*
+ * The follow should be set to reflect the type of system you have:
+ *	JOBS -> 1 if you have Berkeley job control, 0 otherwise.
+ *	SHORTNAMES -> 1 if your linker cannot handle long names.
+ *	define BSD if you are running 4.2 BSD or later.
+ *	define SYSV if you are running under System V.
+ *	define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
+ *	define DEBUG=2 to compile in and turn on debugging.
+ *	define DO_SHAREDVFORK to indicate that vfork(2) shares its address
+ *	       with its parent.
+ *
+ * When debugging is on, debugging info will be written to ./trace and
+ * a quit signal will generate a core dump.
+ */
+
+#include <sys/param.h>
+
+#ifndef JOBS
+#define JOBS 1
+#endif
+#ifndef BSD
+#define BSD 1
+#endif
+
+#ifndef DO_SHAREDVFORK
+#if __NetBSD_Version__ >= 104000000
+#define DO_SHAREDVFORK
+#endif
+#endif
+
+typedef void *pointer;
+#ifndef NULL
+#define NULL (void *)0
+#endif
+#define STATIC static
+#define MKINIT	/* empty */
+
+extern char nullstr[1];		/* null string */
+
+
+#ifdef DEBUG
+#define TRACE(param)	trace param
+#define TRACEV(param)	tracev param
+#else
+#define TRACE(param)
+#define TRACEV(param)
+#endif
+
+#if defined(__GNUC__) && __GNUC__ < 3
+#define va_copy __va_copy
+#endif
+
+#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+#define __builtin_expect(x, expected_value) (x)
+#endif
+
+#define likely(x)	__builtin_expect(!!(x),1)
+#define unlikely(x)	__builtin_expect(!!(x),0)
+
+/*
+ * Hack to calculate maximum length.
+ * (length * 8 - 1) * log10(2) + 1 + 1 + 12
+ * The second 1 is for the minus sign and the 12 is a safety margin.
+ */
+static inline int max_int_length(int bytes)
+{
+	return (bytes * 8 - 1) * 0.30102999566398119521 + 14;
+}
diff --git a/bin/dash/src/show.c b/bin/dash/src/show.c
new file mode 100644
index 00000000..4a049e93
--- /dev/null
+++ b/bin/dash/src/show.c
@@ -0,0 +1,406 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "shell.h"
+#include "parser.h"
+#include "nodes.h"
+#include "mystring.h"
+#include "show.h"
+#include "options.h"
+
+
+#ifdef DEBUG
+static void shtree(union node *, int, char *, FILE*);
+static void shcmd(union node *, FILE *);
+static void sharg(union node *, FILE *);
+static void indent(int, char *, FILE *);
+static void trstring(char *);
+
+
+void
+showtree(union node *n)
+{
+	trputs("showtree called\n");
+	shtree(n, 1, NULL, stdout);
+}
+
+
+static void
+shtree(union node *n, int ind, char *pfx, FILE *fp)
+{
+	struct nodelist *lp;
+	const char *s;
+
+	if (n == NULL)
+		return;
+
+	indent(ind, pfx, fp);
+	switch(n->type) {
+	case NSEMI:
+		s = "; ";
+		goto binop;
+	case NAND:
+		s = " && ";
+		goto binop;
+	case NOR:
+		s = " || ";
+binop:
+		shtree(n->nbinary.ch1, ind, NULL, fp);
+	   /*    if (ind < 0) */
+			fputs(s, fp);
+		shtree(n->nbinary.ch2, ind, NULL, fp);
+		break;
+	case NCMD:
+		shcmd(n, fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	case NPIPE:
+		for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
+			shcmd(lp->n, fp);
+			if (lp->next)
+				fputs(" | ", fp);
+		}
+		if (n->npipe.backgnd)
+			fputs(" &", fp);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	default:
+		fprintf(fp, "<node type %d>", n->type);
+		if (ind >= 0)
+			putc('\n', fp);
+		break;
+	}
+}
+
+
+
+static void
+shcmd(union node *cmd, FILE *fp)
+{
+	union node *np;
+	int first;
+	const char *s;
+	int dftfd;
+
+	first = 1;
+	for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
+		if (! first)
+			putchar(' ');
+		sharg(np, fp);
+		first = 0;
+	}
+	for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
+		if (! first)
+			putchar(' ');
+		switch (np->nfile.type) {
+			case NTO:	s = ">";  dftfd = 1; break;
+			case NCLOBBER:	s = ">|"; dftfd = 1; break;
+			case NAPPEND:	s = ">>"; dftfd = 1; break;
+			case NTOFD:	s = ">&"; dftfd = 1; break;
+			case NFROM:	s = "<";  dftfd = 0; break;
+			case NFROMFD:	s = "<&"; dftfd = 0; break;
+			case NFROMTO:	s = "<>"; dftfd = 0; break;
+			default:  	s = "*error*"; dftfd = 0; break;
+		}
+		if (np->nfile.fd != dftfd)
+			fprintf(fp, "%d", np->nfile.fd);
+		fputs(s, fp);
+		if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
+			fprintf(fp, "%d", np->ndup.dupfd);
+		} else {
+			sharg(np->nfile.fname, fp);
+		}
+		first = 0;
+	}
+}
+
+
+
+static void
+sharg(union node *arg, FILE *fp)
+{
+	char *p;
+	struct nodelist *bqlist;
+	int subtype;
+
+	if (arg->type != NARG) {
+		printf("<node type %d>\n", arg->type);
+		abort();
+	}
+	bqlist = arg->narg.backquote;
+	for (p = arg->narg.text ; *p ; p++) {
+		switch ((signed char)*p) {
+		case CTLESC:
+			putc(*++p, fp);
+			break;
+		case CTLVAR:
+			putc('$', fp);
+			putc('{', fp);
+			subtype = *++p;
+			if (subtype == VSLENGTH)
+				putc('#', fp);
+
+			while (*p != '=')
+				putc(*p++, fp);
+
+			if (subtype & VSNUL)
+				putc(':', fp);
+
+			switch (subtype & VSTYPE) {
+			case VSNORMAL:
+				putc('}', fp);
+				break;
+			case VSMINUS:
+				putc('-', fp);
+				break;
+			case VSPLUS:
+				putc('+', fp);
+				break;
+			case VSQUESTION:
+				putc('?', fp);
+				break;
+			case VSASSIGN:
+				putc('=', fp);
+				break;
+			case VSTRIMLEFT:
+				putc('#', fp);
+				break;
+			case VSTRIMLEFTMAX:
+				putc('#', fp);
+				putc('#', fp);
+				break;
+			case VSTRIMRIGHT:
+				putc('%', fp);
+				break;
+			case VSTRIMRIGHTMAX:
+				putc('%', fp);
+				putc('%', fp);
+				break;
+			case VSLENGTH:
+				break;
+			default:
+				printf("<subtype %d>", subtype);
+			}
+			break;
+		case CTLENDVAR:
+		     putc('}', fp);
+		     break;
+		case CTLBACKQ:
+			putc('$', fp);
+			putc('(', fp);
+			shtree(bqlist->n, -1, NULL, fp);
+			putc(')', fp);
+			break;
+		default:
+			putc(*p, fp);
+			break;
+		}
+	}
+}
+
+
+static void
+indent(int amount, char *pfx, FILE *fp)
+{
+	int i;
+
+	for (i = 0 ; i < amount ; i++) {
+		if (pfx && i == amount - 1)
+			fputs(pfx, fp);
+		putc('\t', fp);
+	}
+}
+
+
+
+/*
+ * Debugging stuff.
+ */
+
+
+FILE *tracefile;
+
+
+void
+trputc(int c)
+{
+	if (debug != 1)
+		return;
+	putc(c, tracefile);
+}
+
+void
+trace(const char *fmt, ...)
+{
+	va_list va;
+
+	if (debug != 1)
+		return;
+	va_start(va, fmt);
+	(void) vfprintf(tracefile, fmt, va);
+	va_end(va);
+}
+
+void
+tracev(const char *fmt, va_list va)
+{
+	if (debug != 1)
+		return;
+	(void) vfprintf(tracefile, fmt, va);
+}
+
+
+void
+trputs(const char *s)
+{
+	if (debug != 1)
+		return;
+	fputs(s, tracefile);
+}
+
+
+static void
+trstring(char *s)
+{
+	char *p;
+	char c;
+
+	if (debug != 1)
+		return;
+	putc('"', tracefile);
+	for (p = s ; *p ; p++) {
+		switch ((signed char)*p) {
+		case '\n':  c = 'n';  goto backslash;
+		case '\t':  c = 't';  goto backslash;
+		case '\r':  c = 'r';  goto backslash;
+		case '"':  c = '"';  goto backslash;
+		case '\\':  c = '\\';  goto backslash;
+		case CTLESC:  c = 'e';  goto backslash;
+		case CTLVAR:  c = 'v';  goto backslash;
+		case CTLBACKQ:  c = 'q';  goto backslash;
+backslash:	  putc('\\', tracefile);
+			putc(c, tracefile);
+			break;
+		default:
+			if (*p >= ' ' && *p <= '~')
+				putc(*p, tracefile);
+			else {
+				putc('\\', tracefile);
+				putc(*p >> 6 & 03, tracefile);
+				putc(*p >> 3 & 07, tracefile);
+				putc(*p & 07, tracefile);
+			}
+			break;
+		}
+	}
+	putc('"', tracefile);
+}
+
+
+void
+trargs(char **ap)
+{
+	if (debug != 1)
+		return;
+	while (*ap) {
+		trstring(*ap++);
+		if (*ap)
+			putc(' ', tracefile);
+		else
+			putc('\n', tracefile);
+	}
+}
+
+
+void
+opentrace(void)
+{
+	char s[100];
+#ifdef O_APPEND
+	int flags;
+#endif
+
+	if (debug != 1) {
+		if (tracefile)
+			fflush(tracefile);
+		/* leave open because libedit might be using it */
+		return;
+	}
+#ifdef not_this_way
+	{
+		char *p;
+		if ((p = getenv(homestr)) == NULL) {
+			if (geteuid() == 0)
+				p = "/";
+			else
+				p = "/tmp";
+		}
+		scopy(p, s);
+		strcat(s, "/trace");
+	}
+#else
+	scopy("./trace", s);
+#endif /* not_this_way */
+	if (tracefile) {
+#ifndef __KLIBC__
+		if (!freopen(s, "a", tracefile)) {
+#else
+		if (!(!fclose(tracefile) && (tracefile = fopen(s, "a")))) {
+#endif /* __KLIBC__ */
+			fprintf(stderr, "Can't re-open %s\n", s);
+			debug = 0;
+			return;
+		}
+	} else {
+		if ((tracefile = fopen(s, "a")) == NULL) {
+			fprintf(stderr, "Can't open %s\n", s);
+			debug = 0;
+			return;
+		}
+	}
+#ifdef O_APPEND
+	if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
+		fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
+#endif
+#ifndef __KLIBC__
+	setlinebuf(tracefile);
+#endif /* __KLIBC__ */
+	fputs("\nTracing started.\n", tracefile);
+}
+#endif /* DEBUG */
diff --git a/bin/dash/src/show.h b/bin/dash/src/show.h
new file mode 100644
index 00000000..d0ccac79
--- /dev/null
+++ b/bin/dash/src/show.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1995
+ *      The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)show.h	1.1 (Berkeley) 5/4/95
+ */
+
+#include <stdarg.h>
+
+#ifdef DEBUG
+union node;
+void showtree(union node *);
+void trace(const char *, ...);
+void tracev(const char *, va_list);
+void trargs(char **);
+void trputc(int);
+void trputs(const char *);
+void opentrace(void);
+#endif
diff --git a/bin/dash/src/system.c b/bin/dash/src/system.c
new file mode 100644
index 00000000..844a6410
--- /dev/null
+++ b/bin/dash/src/system.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2004
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+#ifndef HAVE_ISALPHA
+#define isalnum _isalnum
+#define iscntrl _iscntrl
+#define islower _islower
+#define isspace _isspace
+#define isalpha _isalpha
+#define isdigit _isdigit
+#define isprint _isprint
+#define isupper _isupper
+#define isblank _isblank
+#define isgraph _isgraph
+#define ispunct _ispunct
+#define isxdigit _isxdigit
+#include <ctype.h>
+#undef isalnum
+#undef iscntrl
+#undef islower
+#undef isspace
+#undef isalpha
+#undef isdigit
+#undef isprint
+#undef isupper
+#undef isblank
+#undef isgraph
+#undef ispunct
+#undef isxdigit
+#endif
+
+#include <signal.h>
+#include <string.h>
+
+#include "error.h"
+#include "output.h"
+#include "system.h"
+
+#ifndef HAVE_MEMPCPY
+void *mempcpy(void *dest, const void *src, size_t n)
+{
+	return memcpy(dest, src, n) + n;
+}
+#endif
+
+#ifndef HAVE_STPCPY
+char *stpcpy(char *dest, const char *src)
+{
+	size_t len = strlen(src);
+	dest[len] = 0;
+	return mempcpy(dest, src, len);
+}
+#endif
+
+#ifndef HAVE_STRCHRNUL
+char *strchrnul(const char *s, int c)
+{
+	char *p = strchr(s, c);
+	if (!p)
+		p = (char *)s + strlen(s);
+	return p;
+}
+#endif
+
+#ifndef HAVE_STRSIGNAL
+char *strsignal(int sig)
+{
+	static char buf[19];
+
+	if ((unsigned)sig < NSIG && sys_siglist[sig])
+		return (char *)sys_siglist[sig];
+	fmtstr(buf, sizeof(buf), "Signal %d", sig); 
+	return buf;
+}
+#endif
+
+#ifndef HAVE_BSEARCH
+void *bsearch(const void *key, const void *base, size_t nmemb,
+	      size_t size, int (*cmp)(const void *, const void *))
+{
+	while (nmemb) {
+		size_t mididx = nmemb / 2;
+		const void *midobj = base + mididx * size;
+		int diff = cmp(key, midobj);
+
+		if (diff == 0)
+			return (void *)midobj;
+
+		if (diff > 0) {
+			base = midobj + size;
+			nmemb -= mididx + 1;
+		} else
+			nmemb = mididx;
+	}
+
+	return 0;
+}
+#endif
+
+#ifndef HAVE_SYSCONF
+long sysconf(int name)
+{
+	sh_error("no sysconf for: %d", name);
+}
+#endif
+
+#ifndef HAVE_ISALPHA
+int isalnum(int c) {
+	return _isalnum(c);
+}
+
+
+int iscntrl(int c) {
+	return _iscntrl(c);
+}
+
+
+int islower(int c) {
+	return _islower(c);
+}
+
+
+int isspace(int c) {
+	return _isspace(c);
+}
+
+
+int isalpha(int c) {
+	return _isalpha(c);
+}
+
+
+int isdigit(int c) {
+	return _isdigit(c);
+}
+
+
+int isprint(int c) {
+	return _isprint(c);
+}
+
+
+int isupper(int c) {
+	return _isupper(c);
+}
+
+
+#if HAVE_DECL_ISBLANK
+int isblank(int c) {
+	return _isblank(c);
+}
+#endif
+
+
+int isgraph(int c) {
+	return _isgraph(c);
+}
+
+
+int ispunct(int c) {
+	return _ispunct(c);
+}
+
+
+int isxdigit(int c) {
+	return _isxdigit(c);
+}
+#endif
+
+#if !HAVE_DECL_ISBLANK
+int isblank(int c) {
+	return c == ' ' || c == '\t';
+}
+#endif
diff --git a/bin/dash/src/system.h b/bin/dash/src/system.h
new file mode 100644
index 00000000..007952c5
--- /dev/null
+++ b/bin/dash/src/system.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2004
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ */
+
+#include <limits.h>
+#include <signal.h>
+#include <sys/types.h>
+
+#ifndef SSIZE_MAX
+#define SSIZE_MAX ((ssize_t)((size_t)-1 >> 1))
+#endif
+
+static inline void sigclearmask(void)
+{
+#if defined(HAVE_SIGSETMASK) && \
+    (!defined(__GLIBC__) || \
+     (defined(__GNUC__) && (__GNUC__ * 1000 + __GNUC_MINOR__) >= 4006))
+#ifdef __GLIBC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+	sigsetmask(0);
+#ifdef __GLIBC__
+#pragma GCC diagnostic pop
+#endif
+#else
+	sigset_t set;
+	sigemptyset(&set);
+	sigprocmask(SIG_SETMASK, &set, 0);
+#endif
+}
+
+#ifndef HAVE_MEMPCPY
+void *mempcpy(void *, const void *, size_t);
+#endif
+
+#ifndef HAVE_STPCPY
+char *stpcpy(char *, const char *);
+#endif
+
+#ifndef HAVE_STRCHRNUL
+char *strchrnul(const char *, int);
+#endif
+
+#ifndef HAVE_STRSIGNAL
+char *strsignal(int);
+#endif
+
+#ifndef HAVE_STRTOD
+static inline double strtod(const char *nptr, char **endptr)
+{
+	*endptr = (char *)nptr;
+	return 0;
+}
+#endif
+
+#ifndef HAVE_STRTOIMAX
+#define strtoimax strtoll
+#endif
+
+#ifndef HAVE_STRTOUMAX
+#define strtoumax strtoull
+#endif
+
+#ifndef HAVE_BSEARCH
+void *bsearch(const void *, const void *, size_t, size_t,
+	      int (*)(const void *, const void *));
+#endif
+
+#ifndef HAVE_KILLPG
+static inline int killpg(pid_t pid, int signal)
+{
+#ifdef DEBUG
+	if (pid < 0)
+		abort();
+#endif
+	return kill(-pid, signal);
+}
+#endif
+
+#ifndef HAVE_SYSCONF
+#define _SC_CLK_TCK 2
+long sysconf(int) __attribute__((__noreturn__));
+#endif
+
+#if !HAVE_DECL_ISBLANK
+int isblank(int c);
+#endif
+
+/*
+ * A trick to suppress uninitialized variable warning without generating any
+ * code
+ */
+#define uninitialized_var(x) x = x
diff --git a/bin/dash/src/trap.c b/bin/dash/src/trap.c
new file mode 100644
index 00000000..cd84814f
--- /dev/null
+++ b/bin/dash/src/trap.c
@@ -0,0 +1,446 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "shell.h"
+#include "main.h"
+#include "nodes.h"	/* for other headers */
+#include "eval.h"
+#include "init.h"
+#include "jobs.h"
+#include "show.h"
+#include "options.h"
+#include "syntax.h"
+#include "output.h"
+#include "memalloc.h"
+#include "error.h"
+#include "trap.h"
+#include "mystring.h"
+
+/*
+ * Sigmode records the current value of the signal handlers for the various
+ * modes.  A value of zero means that the current handler is not known.
+ * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
+ */
+
+#define S_DFL 1			/* default signal handling (SIG_DFL) */
+#define S_CATCH 2		/* signal is caught */
+#define S_IGN 3			/* signal is ignored (SIG_IGN) */
+#define S_HARD_IGN 4		/* signal is ignored permenantly */
+#define S_RESET 5		/* temporary - to reset a hard ignored sig */
+
+
+/* trap handler commands */
+MKINIT char *trap[NSIG];
+/* number of non-null traps */
+int trapcnt;
+/* current value of signal */
+char sigmode[NSIG - 1];
+/* indicates specified signal received */
+static char gotsig[NSIG - 1];
+/* last pending signal */
+volatile sig_atomic_t pending_sig;
+/* received SIGCHLD */
+volatile sig_atomic_t gotsigchld;
+
+extern char *signal_names[];
+
+static int decode_signum(const char *);
+
+#ifdef mkinit
+INCLUDE "memalloc.h"
+INCLUDE "trap.h"
+
+INIT {
+	sigmode[SIGCHLD - 1] = S_DFL;
+	setsignal(SIGCHLD);
+}
+
+FORKRESET {
+	char **tp;
+
+	INTOFF;
+	for (tp = trap ; tp < &trap[NSIG] ; tp++) {
+		if (*tp && **tp) {	/* trap not NULL or SIG_IGN */
+			ckfree(*tp);
+			*tp = NULL;
+			if (tp != &trap[0])
+				setsignal(tp - trap);
+		}
+	}
+	trapcnt = 0;
+	INTON;
+}
+#endif
+
+/*
+ * The trap builtin.
+ */
+
+int
+trapcmd(int argc, char **argv)
+{
+	char *action;
+	char **ap;
+	int signo;
+
+	nextopt(nullstr);
+	ap = argptr;
+	if (!*ap) {
+		for (signo = 0 ; signo < NSIG ; signo++) {
+			if (trap[signo] != NULL) {
+				out1fmt(
+					"trap -- %s %s\n",
+					single_quote(trap[signo]),
+					signal_names[signo]
+				);
+			}
+		}
+		return 0;
+	}
+	if (!ap[1] || decode_signum(*ap) >= 0)
+		action = NULL;
+	else
+		action = *ap++;
+	while (*ap) {
+		if ((signo = decode_signal(*ap, 0)) < 0) {
+			outfmt(out2, "trap: %s: bad trap\n", *ap);
+			return 1;
+		}
+		INTOFF;
+		if (action) {
+			if (action[0] == '-' && action[1] == '\0')
+				action = NULL;
+			else {
+				if (*action)
+					trapcnt++;
+				action = savestr(action);
+			}
+		}
+		if (trap[signo]) {
+			if (*trap[signo])
+				trapcnt--;
+			ckfree(trap[signo]);
+		}
+		trap[signo] = action;
+		if (signo != 0)
+			setsignal(signo);
+		INTON;
+		ap++;
+	}
+	return 0;
+}
+
+
+
+/*
+ * Set the signal handler for the specified signal.  The routine figures
+ * out what it should be set to.
+ */
+
+void
+setsignal(int signo)
+{
+	int action;
+	int lvforked;
+	char *t, tsig;
+	struct sigaction act;
+
+	lvforked = vforked;
+
+	if ((t = trap[signo]) == NULL)
+		action = S_DFL;
+	else if (*t != '\0')
+		action = S_CATCH;
+	else
+		action = S_IGN;
+	if (rootshell && action == S_DFL && !lvforked) {
+		switch (signo) {
+		case SIGINT:
+			if (iflag || minusc || sflag == 0)
+				action = S_CATCH;
+			break;
+		case SIGQUIT:
+#ifdef DEBUG
+			if (debug)
+				break;
+#endif
+			/* FALLTHROUGH */
+		case SIGTERM:
+			if (iflag)
+				action = S_IGN;
+			break;
+#if JOBS
+		case SIGTSTP:
+		case SIGTTOU:
+			if (mflag)
+				action = S_IGN;
+			break;
+#endif
+		}
+	}
+
+	if (signo == SIGCHLD)
+		action = S_CATCH;
+
+	t = &sigmode[signo - 1];
+	tsig = *t;
+	if (tsig == 0) {
+		/*
+		 * current setting unknown
+		 */
+		if (sigaction(signo, 0, &act) == -1) {
+			/*
+			 * Pretend it worked; maybe we should give a warning
+			 * here, but other shells don't. We don't alter
+			 * sigmode, so that we retry every time.
+			 */
+			return;
+		}
+		if (act.sa_handler == SIG_IGN) {
+			if (mflag && (signo == SIGTSTP ||
+			     signo == SIGTTIN || signo == SIGTTOU)) {
+				tsig = S_IGN;	/* don't hard ignore these */
+			} else
+				tsig = S_HARD_IGN;
+		} else {
+			tsig = S_RESET;	/* force to be set */
+		}
+	}
+	if (tsig == S_HARD_IGN || tsig == action)
+		return;
+	switch (action) {
+	case S_CATCH:
+		act.sa_handler = onsig;
+		break;
+	case S_IGN:
+		act.sa_handler = SIG_IGN;
+		break;
+	default:
+		act.sa_handler = SIG_DFL;
+	}
+	if (!lvforked)
+		*t = action;
+	act.sa_flags = 0;
+	sigfillset(&act.sa_mask);
+	sigaction(signo, &act, 0);
+}
+
+/*
+ * Ignore a signal.
+ */
+
+void
+ignoresig(int signo)
+{
+	if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
+		signal(signo, SIG_IGN);
+	}
+	if (!vforked)
+		sigmode[signo - 1] = S_HARD_IGN;
+}
+
+
+
+/*
+ * Signal handler.
+ */
+
+void
+onsig(int signo)
+{
+	if (vforked)
+		return;
+
+	if (signo == SIGCHLD) {
+		gotsigchld = 1;
+		if (!trap[SIGCHLD])
+			return;
+	}
+
+	gotsig[signo - 1] = 1;
+	pending_sig = signo;
+
+	if (signo == SIGINT && !trap[SIGINT]) {
+		if (!suppressint)
+			onint();
+		intpending = 1;
+	}
+}
+
+
+
+/*
+ * Called to execute a trap.  Perhaps we should avoid entering new trap
+ * handlers while we are executing a trap handler.
+ */
+
+void dotrap(void)
+{
+	char *p;
+	char *q;
+	int i;
+	int status, last_status;
+
+	if (!pending_sig)
+		return;
+
+	status = savestatus;
+	last_status = status;
+	if (likely(status < 0)) {
+		status = exitstatus;
+		savestatus = status;
+	}
+	pending_sig = 0;
+	barrier();
+
+	for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
+		if (!*q)
+			continue;
+
+		if (evalskip) {
+			pending_sig = i + 1;
+			break;
+		}
+
+		*q = 0;
+
+		p = trap[i + 1];
+		if (!p)
+			continue;
+		evalstring(p, 0);
+		if (evalskip != SKIPFUNC)
+			exitstatus = status;
+	}
+
+	savestatus = last_status;
+}
+
+
+
+/*
+ * Controls whether the shell is interactive or not.
+ */
+
+
+void
+setinteractive(int on)
+{
+	static int is_interactive;
+
+	if (++on == is_interactive)
+		return;
+	is_interactive = on;
+	setsignal(SIGINT);
+	setsignal(SIGQUIT);
+	setsignal(SIGTERM);
+}
+
+
+
+/*
+ * Called to exit the shell.
+ */
+
+void
+exitshell(void)
+{
+	struct jmploc loc;
+	char *p;
+
+	savestatus = exitstatus;
+	TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus));
+	if (setjmp(loc.loc))
+		goto out;
+	handler = &loc;
+	if ((p = trap[0])) {
+		trap[0] = NULL;
+		evalskip = 0;
+		evalstring(p, 0);
+		evalskip = SKIPFUNCDEF;
+	}
+out:
+	exitreset();
+	/*
+	 * Disable job control so that whoever had the foreground before we
+	 * started can get it back.
+	 */
+	if (likely(!setjmp(loc.loc)))
+		setjobctl(0);
+	flushall();
+	_exit(exitstatus);
+	/* NOTREACHED */
+}
+
+static int decode_signum(const char *string)
+{
+	int signo = -1;
+
+	if (is_number(string)) {
+		signo = atoi(string);
+		if (signo >= NSIG)
+			signo = -1;
+	}
+
+	return signo;
+}
+
+int decode_signal(const char *string, int minsig)
+{
+	int signo;
+
+	signo = decode_signum(string);
+	if (signo >= 0)
+		return signo;
+
+	for (signo = minsig; signo < NSIG; signo++) {
+		if (!strcasecmp(string, signal_names[signo])) {
+			return signo;
+		}
+	}
+
+	return -1;
+}
+
+void sigblockall(sigset_t *oldmask)
+{
+	sigset_t mask;
+
+	sigfillset(&mask);
+	sigprocmask(SIG_SETMASK, &mask, oldmask);
+}
diff --git a/bin/dash/src/trap.h b/bin/dash/src/trap.h
new file mode 100644
index 00000000..beaf6605
--- /dev/null
+++ b/bin/dash/src/trap.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)trap.h	8.3 (Berkeley) 6/5/95
+ */
+
+#include <signal.h>
+
+extern int trapcnt;
+extern char sigmode[];
+extern volatile sig_atomic_t pending_sig;
+extern volatile sig_atomic_t gotsigchld;
+
+int trapcmd(int, char **);
+void setsignal(int);
+void ignoresig(int);
+void onsig(int);
+void dotrap(void);
+void setinteractive(int);
+void exitshell(void) __attribute__((__noreturn__));
+int decode_signal(const char *, int);
+void sigblockall(sigset_t *oldmask);
+
+static inline int have_traps(void)
+{
+	return trapcnt;
+}
diff --git a/bin/dash/src/var.c b/bin/dash/src/var.c
new file mode 100644
index 00000000..ca9504ef
--- /dev/null
+++ b/bin/dash/src/var.c
@@ -0,0 +1,676 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+/*
+ * Shell variables.
+ */
+
+#include "shell.h"
+#include "output.h"
+#include "expand.h"
+#include "nodes.h"	/* for other headers */
+#include "exec.h"
+#include "syntax.h"
+#include "options.h"
+#include "mail.h"
+#include "var.h"
+#include "memalloc.h"
+#include "error.h"
+#include "mystring.h"
+#include "parser.h"
+#include "show.h"
+#ifndef SMALL
+#include "myhistedit.h"
+#endif
+#include "system.h"
+
+
+#define VTABSIZE 39
+
+
+struct localvar_list {
+	struct localvar_list *next;
+	struct localvar *lv;
+};
+
+MKINIT struct localvar_list *localvar_stack;
+
+const char defpathvar[] =
+	"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
+char defifsvar[] = "IFS= \t\n";
+MKINIT char defoptindvar[] = "OPTIND=1";
+
+int lineno;
+char linenovar[sizeof("LINENO=")+sizeof(int)*CHAR_BIT/3+1] = "LINENO=";
+
+/* Some macros in var.h depend on the order, add new variables to the end. */
+struct var varinit[] = {
+#if ATTY
+	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"ATTY\0",	0 },
+#endif
+	{ 0,	VSTRFIXED|VTEXTFIXED,		defifsvar,	0 },
+	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAIL\0",	changemail },
+	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"MAILPATH\0",	changemail },
+	{ 0,	VSTRFIXED|VTEXTFIXED,		defpathvar,	changepath },
+	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS1=$ ",	0 },
+	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS2=> ",	0 },
+	{ 0,	VSTRFIXED|VTEXTFIXED,		"PS4=+ ",	0 },
+	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"RPS1\0",	0 },
+	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"RPS2\0",	0 },
+	{ 0,	VSTRFIXED|VTEXTFIXED,		defoptindvar,	getoptsreset },
+#ifdef WITH_LINENO
+	{ 0,	VSTRFIXED|VTEXTFIXED,		linenovar,	0 },
+#endif
+#ifndef SMALL
+	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"TERM\0",	0 },
+	{ 0,	VSTRFIXED|VTEXTFIXED|VUNSET,	"HISTSIZE\0",	sethistsize },
+#endif
+};
+
+STATIC struct var *vartab[VTABSIZE];
+
+STATIC struct var **hashvar(const char *);
+STATIC int vpcmp(const void *, const void *);
+STATIC struct var **findvar(struct var **, const char *);
+
+/*
+ * Initialize the varable symbol tables and import the environment
+ */
+
+#ifdef mkinit
+INCLUDE <unistd.h>
+INCLUDE <sys/types.h>
+INCLUDE <sys/stat.h>
+INCLUDE "cd.h"
+INCLUDE "output.h"
+INCLUDE "var.h"
+MKINIT char **environ;
+INIT {
+	char **envp;
+	static char ppid[32] = "PPID=";
+	const char *p;
+	struct stat64 st1, st2;
+
+	initvar();
+	for (envp = environ ; *envp ; envp++) {
+		p = endofname(*envp);
+		if (p != *envp && *p == '=') {
+			setvareq(*envp, VEXPORT|VTEXTFIXED);
+		}
+	}
+
+	setvareq(defifsvar, VTEXTFIXED);
+	setvareq(defoptindvar, VTEXTFIXED);
+
+	fmtstr(ppid + 5, sizeof(ppid) - 5, "%ld", (long) getppid());
+	setvareq(ppid, VTEXTFIXED);
+
+	p = lookupvar("PWD");
+	if (p)
+		if (*p != '/' || stat64(p, &st1) || stat64(".", &st2) ||
+		    st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
+			p = 0;
+	setpwd(p, 0);
+}
+
+RESET {
+	unwindlocalvars(0);
+}
+#endif
+
+
+/*
+ * This routine initializes the builtin variables.  It is called when the
+ * shell is initialized.
+ */
+
+void
+initvar(void)
+{
+	struct var *vp;
+	struct var *end;
+	struct var **vpp;
+
+	vp = varinit;
+	end = vp + sizeof(varinit) / sizeof(varinit[0]);
+	do {
+		vpp = hashvar(vp->text);
+		vp->next = *vpp;
+		*vpp = vp;
+	} while (++vp < end);
+	/*
+	 * PS1 depends on uid
+	 */
+	if (!geteuid())
+		vps1.text = "PS1=# ";
+}
+
+/*
+ * Set the value of a variable.  The flags argument is ored with the
+ * flags of the variable.  If val is NULL, the variable is unset.
+ */
+
+struct var *setvar(const char *name, const char *val, int flags)
+{
+	char *p, *q;
+	size_t namelen;
+	char *nameeq;
+	size_t vallen;
+	struct var *vp;
+
+	q = endofname(name);
+	p = strchrnul(q, '=');
+	namelen = p - name;
+	if (!namelen || p != q)
+		sh_error("%.*s: bad variable name", namelen, name);
+	vallen = 0;
+	if (val == NULL) {
+		flags |= VUNSET;
+	} else {
+		vallen = strlen(val);
+	}
+	INTOFF;
+	p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
+	if (val) {
+		*p++ = '=';
+		p = mempcpy(p, val, vallen);
+	}
+	*p = '\0';
+	vp = setvareq(nameeq, flags | VNOSAVE);
+	INTON;
+
+	return vp;
+}
+
+/*
+ * Set the given integer as the value of a variable.  The flags argument is
+ * ored with the flags of the variable.
+ */
+
+intmax_t setvarint(const char *name, intmax_t val, int flags)
+{
+	int len = max_int_length(sizeof(val));
+	char buf[len];
+
+	fmtstr(buf, len, "%" PRIdMAX, val);
+	setvar(name, buf, flags);
+	return val;
+}
+
+
+
+/*
+ * Same as setvar except that the variable and value are passed in
+ * the first argument as name=value.  Since the first argument will
+ * be actually stored in the table, it should not be a string that
+ * will go away.
+ * Called with interrupts off.
+ */
+
+struct var *setvareq(char *s, int flags)
+{
+	struct var *vp, **vpp;
+
+	vpp = hashvar(s);
+	flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
+	vpp = findvar(vpp, s);
+	vp = *vpp;
+	if (vp) {
+		if (vp->flags & VREADONLY) {
+			const char *n;
+
+			if (flags & VNOSAVE)
+				free(s);
+			n = vp->text;
+			sh_error("%.*s: is read only", strchrnul(n, '=') - n,
+				 n);
+		}
+
+		if (flags & VNOSET)
+			goto out;
+
+		if (vp->func && (flags & VNOFUNC) == 0)
+			(*vp->func)(strchrnul(s, '=') + 1);
+
+		if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
+			ckfree(vp->text);
+
+		if (((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) |
+		     (vp->flags & VSTRFIXED)) == VUNSET) {
+			*vpp = vp->next;
+			ckfree(vp);
+out_free:
+			if ((flags & (VTEXTFIXED|VSTACK|VNOSAVE)) == VNOSAVE)
+				ckfree(s);
+			goto out;
+		}
+
+		flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
+	} else {
+		if (flags & VNOSET)
+			goto out;
+		if ((flags & (VEXPORT|VREADONLY|VSTRFIXED|VUNSET)) == VUNSET)
+			goto out_free;
+		/* not found */
+		vp = ckmalloc(sizeof (*vp));
+		vp->next = *vpp;
+		vp->func = NULL;
+		*vpp = vp;
+	}
+	if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
+		s = savestr(s);
+	vp->text = s;
+	vp->flags = flags;
+
+out:
+	return vp;
+}
+
+/*
+ * Find the value of a variable.  Returns NULL if not set.
+ */
+
+char *
+lookupvar(const char *name)
+{
+	struct var *v;
+
+	if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
+#ifdef WITH_LINENO
+		if (v == &vlineno && v->text == linenovar) {
+			fmtstr(linenovar+7, sizeof(linenovar)-7, "%d", lineno);
+		}
+#endif
+		return strchrnul(v->text, '=') + 1;
+	}
+	return NULL;
+}
+
+intmax_t lookupvarint(const char *name)
+{
+	return atomax(lookupvar(name) ?: nullstr, 0);
+}
+
+
+
+/*
+ * Generate a list of variables satisfying the given conditions.
+ */
+
+char **
+listvars(int on, int off, char ***end)
+{
+	struct var **vpp;
+	struct var *vp;
+	char **ep;
+	int mask;
+
+	STARTSTACKSTR(ep);
+	vpp = vartab;
+	mask = on | off;
+	do {
+		for (vp = *vpp ; vp ; vp = vp->next)
+			if ((vp->flags & mask) == on) {
+				if (ep == stackstrend())
+					ep = growstackstr();
+				*ep++ = (char *) vp->text;
+			}
+	} while (++vpp < vartab + VTABSIZE);
+	if (ep == stackstrend())
+		ep = growstackstr();
+	if (end)
+		*end = ep;
+	*ep++ = NULL;
+	return grabstackstr(ep);
+}
+
+
+
+/*
+ * POSIX requires that 'set' (but not export or readonly) output the
+ * variables in lexicographic order - by the locale's collating order (sigh).
+ * Maybe we could keep them in an ordered balanced binary tree
+ * instead of hashed lists.
+ * For now just roll 'em through qsort for printing...
+ */
+
+int
+showvars(const char *prefix, int on, int off)
+{
+	const char *sep;
+	char **ep, **epend;
+
+	ep = listvars(on, off, &epend);
+	qsort(ep, epend - ep, sizeof(char *), vpcmp);
+
+	sep = *prefix ? spcstr : prefix;
+
+	for (; ep < epend; ep++) {
+		const char *p;
+		const char *q;
+
+		p = strchrnul(*ep, '=');
+		q = nullstr;
+		if (*p)
+			q = single_quote(++p);
+
+		out1fmt("%s%s%.*s%s\n", prefix, sep, (int)(p - *ep), *ep, q);
+	}
+
+	return 0;
+}
+
+
+
+/*
+ * The export and readonly commands.
+ */
+
+int
+exportcmd(int argc, char **argv)
+{
+	struct var *vp;
+	char *name;
+	const char *p;
+	char **aptr;
+	int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
+	int notp;
+
+	notp = nextopt("p") - 'p';
+	if (notp && ((name = *(aptr = argptr)))) {
+		do {
+			if ((p = strchr(name, '=')) != NULL) {
+				p++;
+			} else {
+				if ((vp = *findvar(hashvar(name), name))) {
+					vp->flags |= flag;
+					continue;
+				}
+			}
+			setvar(name, p, flag);
+		} while ((name = *++aptr) != NULL);
+	} else {
+		showvars(argv[0], flag, 0);
+	}
+	return 0;
+}
+
+
+/*
+ * The "local" command.
+ */
+
+int
+localcmd(int argc, char **argv)
+{
+	char *name;
+
+	if (!localvar_stack)
+		sh_error("not in a function");
+
+	argv = argptr;
+	while ((name = *argv++) != NULL) {
+		mklocal(name, 0);
+	}
+	return 0;
+}
+
+
+/*
+ * Make a variable a local variable.  When a variable is made local, it's
+ * value and flags are saved in a localvar structure.  The saved values
+ * will be restored when the shell function returns.  We handle the name
+ * "-" as a special case.
+ */
+
+void mklocal(char *name, int flags)
+{
+	struct localvar *lvp;
+	struct var **vpp;
+	struct var *vp;
+
+	INTOFF;
+	lvp = ckmalloc(sizeof (struct localvar));
+	if (name[0] == '-' && name[1] == '\0') {
+		char *p;
+		p = ckmalloc(sizeof(optlist));
+		lvp->text = memcpy(p, optlist, sizeof(optlist));
+		vp = NULL;
+	} else {
+		char *eq;
+
+		vpp = hashvar(name);
+		vp = *findvar(vpp, name);
+		eq = strchr(name, '=');
+		if (vp == NULL) {
+			if (eq)
+				vp = setvareq(name, VSTRFIXED | flags);
+			else
+				vp = setvar(name, NULL, VSTRFIXED | flags);
+			lvp->flags = VUNSET;
+		} else {
+			lvp->text = vp->text;
+			lvp->flags = vp->flags;
+			vp->flags |= VSTRFIXED|VTEXTFIXED;
+			if (eq)
+				setvareq(name, flags);
+		}
+	}
+	lvp->vp = vp;
+	lvp->next = localvar_stack->lv;
+	localvar_stack->lv = lvp;
+	INTON;
+}
+
+
+/*
+ * Called after a function returns.
+ * Interrupts must be off.
+ */
+
+static void
+poplocalvars(void)
+{
+	struct localvar_list *ll;
+	struct localvar *lvp, *next;
+	struct var *vp;
+
+	INTOFF;
+	ll = localvar_stack;
+	localvar_stack = ll->next;
+
+	next = ll->lv;
+	ckfree(ll);
+
+	while ((lvp = next) != NULL) {
+		next = lvp->next;
+		vp = lvp->vp;
+		TRACE(("poplocalvar %s\n", vp ? vp->text : "-"));
+		if (vp == NULL) {	/* $- saved */
+			memcpy(optlist, lvp->text, sizeof(optlist));
+			ckfree(lvp->text);
+			optschanged();
+		} else if (lvp->flags == VUNSET) {
+			vp->flags &= ~(VSTRFIXED|VREADONLY);
+			unsetvar(vp->text);
+		} else {
+			if (vp->func)
+				(*vp->func)(strchrnul(lvp->text, '=') + 1);
+			if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
+				ckfree(vp->text);
+			vp->flags = lvp->flags;
+			vp->text = lvp->text;
+		}
+		ckfree(lvp);
+	}
+	INTON;
+}
+
+
+/*
+ * Create a new localvar environment.
+ */
+struct localvar_list *pushlocalvars(int push)
+{
+	struct localvar_list *ll;
+	struct localvar_list *top;
+
+	top = localvar_stack;
+	if (!push)
+		goto out;
+
+	INTOFF;
+	ll = ckmalloc(sizeof(*ll));
+	ll->lv = NULL;
+	ll->next = top;
+	localvar_stack = ll;
+	INTON;
+
+out:
+	return top;
+}
+
+
+void unwindlocalvars(struct localvar_list *stop)
+{
+	while (localvar_stack != stop)
+		poplocalvars();
+}
+
+
+/*
+ * The unset builtin command.  We unset the function before we unset the
+ * variable to allow a function to be unset when there is a readonly variable
+ * with the same name.
+ */
+
+int
+unsetcmd(int argc, char **argv)
+{
+	char **ap;
+	int i;
+	int flag = 0;
+
+	while ((i = nextopt("vf")) != '\0') {
+		flag = i;
+	}
+
+	for (ap = argptr; *ap ; ap++) {
+		if (flag != 'f') {
+			unsetvar(*ap);
+			continue;
+		}
+		if (flag != 'v')
+			unsetfunc(*ap);
+	}
+	return 0;
+}
+
+
+/*
+ * Unset the specified variable.
+ */
+
+void unsetvar(const char *s)
+{
+	setvar(s, 0, 0);
+}
+
+
+
+/*
+ * Find the appropriate entry in the hash table from the name.
+ */
+
+STATIC struct var **
+hashvar(const char *p)
+{
+	unsigned int hashval;
+
+	hashval = ((unsigned char) *p) << 4;
+	while (*p && *p != '=')
+		hashval += (unsigned char) *p++;
+	return &vartab[hashval % VTABSIZE];
+}
+
+
+
+/*
+ * Compares two strings up to the first = or '\0'.  The first
+ * string must be terminated by '='; the second may be terminated by
+ * either '=' or '\0'.
+ */
+
+int
+varcmp(const char *p, const char *q)
+{
+	int c, d;
+
+	while ((c = *p) == (d = *q)) {
+		if (!c || c == '=')
+			goto out;
+		p++;
+		q++;
+	}
+	if (c == '=')
+		c = 0;
+	if (d == '=')
+		d = 0;
+out:
+	return c - d;
+}
+
+STATIC int
+vpcmp(const void *a, const void *b)
+{
+	return varcmp(*(const char **)a, *(const char **)b);
+}
+
+STATIC struct var **
+findvar(struct var **vpp, const char *name)
+{
+	for (; *vpp; vpp = &(*vpp)->next) {
+		if (varequal((*vpp)->text, name)) {
+			break;
+		}
+	}
+	return vpp;
+}
diff --git a/bin/dash/src/var.h b/bin/dash/src/var.h
new file mode 100644
index 00000000..1d1d87a5
--- /dev/null
+++ b/bin/dash/src/var.h
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 1997-2005
+ *	Herbert Xu <herbert@gondor.apana.org.au>.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Kenneth Almquist.
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)var.h	8.2 (Berkeley) 5/4/95
+ */
+
+#include <inttypes.h>
+
+/*
+ * Shell variables.
+ */
+
+/* flags */
+#define VEXPORT		0x01	/* variable is exported */
+#define VREADONLY	0x02	/* variable cannot be modified */
+#define VSTRFIXED	0x04	/* variable struct is statically allocated */
+#define VTEXTFIXED	0x08	/* text is statically allocated */
+#define VSTACK		0x10	/* text is allocated on the stack */
+#define VUNSET		0x20	/* the variable is not set */
+#define VNOFUNC		0x40	/* don't call the callback function */
+#define VNOSET		0x80	/* do not set variable - just readonly test */
+#define VNOSAVE		0x100	/* when text is on the heap before setvareq */
+
+
+struct var {
+	struct var *next;		/* next entry in hash list */
+	int flags;			/* flags are defined above */
+	const char *text;		/* name=value */
+	void (*func)(const char *);
+					/* function to be called when  */
+					/* the variable gets set/unset */
+};
+
+
+struct localvar {
+	struct localvar *next;		/* next local variable in list */
+	struct var *vp;			/* the variable that was made local */
+	int flags;			/* saved flags */
+	const char *text;		/* saved text */
+};
+
+struct localvar_list;
+
+
+extern struct localvar *localvars;
+extern struct var varinit[];
+
+#if ATTY
+#define vatty varinit[0]
+#define vifs varinit[1]
+#else
+#define vifs varinit[0]
+#endif
+#define vmail (&vifs)[1]
+#define vmpath (&vmail)[1]
+#define vpath (&vmpath)[1]
+#define vps1 (&vpath)[1]
+#define vps2 (&vps1)[1]
+#define vps4 (&vps2)[1]
+#define vrps1 (&vps4)[1]
+#define vrps2 (&vrps1)[1]
+#define voptind (&vrps2)[1]
+#ifdef WITH_LINENO
+#define vlineno (&voptind)[1]
+#endif
+#ifndef SMALL
+#ifdef WITH_LINENO
+#define vterm (&vlineno)[1]
+#else
+#define vterm (&voptind)[1]
+#endif
+#define vhistsize (&vterm)[1]
+#endif
+
+extern char defifsvar[];
+#define defifs (defifsvar + 4)
+extern const char defpathvar[];
+#define defpath (defpathvar + 36)
+
+extern int lineno;
+extern char linenovar[];
+
+/*
+ * The following macros access the values of the above variables.
+ * They have to skip over the name.  They return the null string
+ * for unset variables.
+ */
+
+#define ifsval()	(vifs.text + 4)
+#define ifsset()	((vifs.flags & VUNSET) == 0)
+#define mailval()	(vmail.text + 5)
+#define mpathval()	(vmpath.text + 9)
+#define pathval()	(vpath.text + 5)
+#define ps1val()	(vps1.text + 4)
+#define ps2val()	(vps2.text + 4)
+#define ps4val()	(vps4.text + 4)
+#define rps1val()	(vrps1.text + 5)
+#define rps2val()	(vrps2.text + 5)
+#define optindval()	(voptind.text + 7)
+#define linenoval()	(vlineno.text + 7)
+#ifndef SMALL
+#define histsizeval()	(vhistsize.text + 9)
+#define termval()	(vterm.text + 5)
+#endif
+
+#if ATTY
+#define attyset()	((vatty.flags & VUNSET) == 0)
+#endif
+#define mpathset()	((vmpath.flags & VUNSET) == 0)
+
+void initvar(void);
+struct var *setvar(const char *name, const char *val, int flags);
+intmax_t setvarint(const char *, intmax_t, int);
+struct var *setvareq(char *s, int flags);
+struct strlist;
+char *lookupvar(const char *);
+intmax_t lookupvarint(const char *);
+char **listvars(int, int, char ***);
+#define environment() listvars(VEXPORT, VUNSET, 0)
+int showvars(const char *, int, int);
+int exportcmd(int, char **);
+int localcmd(int, char **);
+void mklocal(char *name, int flags);
+struct localvar_list *pushlocalvars(int push);
+void unwindlocalvars(struct localvar_list *stop);
+int unsetcmd(int, char **);
+void unsetvar(const char *);
+int varcmp(const char *, const char *);
+
+static inline int varequal(const char *a, const char *b) {
+	return !varcmp(a, b);
+}
+
+/*
+ * Search the environment of a builtin command.
+ */
+
+static inline char *bltinlookup(const char *name)
+{
+	return lookupvar(name);
+}
+
+
diff --git a/bin/dtch.c b/bin/dtch.c
new file mode 100644
index 00000000..026493dd
--- /dev/null
+++ b/bin/dtch.c
@@ -0,0 +1,271 @@
+/* Copyright (C) 2017-2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
+
+#if defined __FreeBSD__
+#include <libutil.h>
+#elif defined __linux__
+#include <pty.h>
+#else
+#include <util.h>
+#endif
+
+static char _;
+static struct iovec iov = { .iov_base = &_, .iov_len = 1 };
+
+static ssize_t sendfd(int sock, int fd) {
+	size_t len = CMSG_SPACE(sizeof(int));
+	char buf[len];
+	struct msghdr msg = {
+		.msg_iov = &iov,
+		.msg_iovlen = 1,
+		.msg_control = buf,
+		.msg_controllen = len,
+	};
+
+	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_RIGHTS;
+	*(int *)CMSG_DATA(cmsg) = fd;
+
+	return sendmsg(sock, &msg, 0);
+}
+
+static int recvfd(int sock) {
+	size_t len = CMSG_SPACE(sizeof(int));
+	char buf[len];
+	struct msghdr msg = {
+		.msg_iov = &iov,
+		.msg_iovlen = 1,
+		.msg_control = buf,
+		.msg_controllen = len,
+	};
+	if (0 > recvmsg(sock, &msg, 0)) return -1;
+
+	struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
+	if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) {
+		errno = ENOMSG;
+		return -1;
+	}
+	return *(int *)CMSG_DATA(cmsg);
+}
+
+static struct sockaddr_un addr = { .sun_family = AF_UNIX };
+
+static void handler(int sig) {
+	unlink(addr.sun_path);
+	_exit(-sig);
+}
+
+static void detach(int server, bool sink, char *argv[]) {
+	int pty;
+	pid_t pid = forkpty(&pty, NULL, NULL, NULL);
+	if (pid < 0) err(EX_OSERR, "forkpty");
+
+	if (!pid) {
+		execvp(argv[0], argv);
+		err(EX_NOINPUT, "%s", argv[0]);
+	}
+
+	signal(SIGINT, handler);
+	signal(SIGTERM, handler);
+
+	int error = listen(server, 0);
+	if (error) err(EX_OSERR, "listen");
+
+	struct pollfd fds[] = {
+		{ .events = POLLIN, .fd = server },
+		{ .events = POLLIN, .fd = pty },
+	};
+	while (0 < poll(fds, (sink ? 2 : 1), -1)) {
+		if (fds[0].revents) {
+			int client = accept(server, NULL, NULL);
+			if (client < 0) err(EX_IOERR, "accept");
+
+			ssize_t len = sendfd(client, pty);
+			if (len < 0) warn("sendfd");
+
+			len = recv(client, &_, sizeof(_), 0);
+			if (len < 0) warn("recv");
+
+			close(client);
+		}
+
+		if (fds[1].revents) {
+			char buf[4096];
+			ssize_t len = read(pty, buf, sizeof(buf));
+			if (len < 0) err(EX_IOERR, "read");
+		}
+
+		int status;
+		pid_t dead = waitpid(pid, &status, WNOHANG);
+		if (dead < 0) err(EX_OSERR, "waitpid");
+		if (dead) {
+			unlink(addr.sun_path);
+			exit(WIFEXITED(status) ? WEXITSTATUS(status) : -WTERMSIG(status));
+		}
+	}
+	err(EX_IOERR, "poll");
+}
+
+static struct termios saveTerm;
+static void restoreTerm(void) {
+	tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm);
+	fprintf(stderr, "\33c"); // RIS
+	warnx("detached");
+}
+
+static void nop(int sig) {
+	(void)sig;
+}
+
+static void attach(int client) {
+	int error;
+
+	int pty = recvfd(client);
+	if (pty < 0) err(EX_IOERR, "recvfd");
+	warnx("attached");
+
+	struct winsize window;
+	error = ioctl(STDIN_FILENO, TIOCGWINSZ, &window);
+	if (error) err(EX_IOERR, "ioctl");
+
+	struct winsize redraw = { .ws_row = 1, .ws_col = 1 };
+	error = ioctl(pty, TIOCSWINSZ, &redraw);
+	if (error) err(EX_IOERR, "ioctl");
+
+	error = ioctl(pty, TIOCSWINSZ, &window);
+	if (error) err(EX_IOERR, "ioctl");
+
+	error = tcgetattr(STDIN_FILENO, &saveTerm);
+	if (error) err(EX_IOERR, "tcgetattr");
+	atexit(restoreTerm);
+
+	struct termios raw = saveTerm;
+	cfmakeraw(&raw);
+	error = tcsetattr(STDIN_FILENO, TCSADRAIN, &raw);
+	if (error) err(EX_IOERR, "tcsetattr");
+
+	signal(SIGWINCH, nop);
+
+	char buf[4096];
+	struct pollfd fds[] = {
+		{ .events = POLLIN, .fd = STDIN_FILENO },
+		{ .events = POLLIN, .fd = pty },
+	};
+	for (;;) {
+		int nfds = poll(fds, 2, -1);
+		if (nfds < 0) {
+			if (errno != EINTR) err(EX_IOERR, "poll");
+
+			error = ioctl(STDIN_FILENO, TIOCGWINSZ, &window);
+			if (error) err(EX_IOERR, "ioctl");
+
+			error = ioctl(pty, TIOCSWINSZ, &window);
+			if (error) err(EX_IOERR, "ioctl");
+
+			continue;
+		}
+
+		if (fds[0].revents) {
+			ssize_t len = read(STDIN_FILENO, buf, sizeof(buf));
+			if (len < 0) err(EX_IOERR, "read");
+			if (!len) break;
+
+			if (len == 1 && buf[0] == CTRL('Q')) break;
+
+			len = write(pty, buf, len);
+			if (len < 0) err(EX_IOERR, "write");
+		}
+
+		if (fds[1].revents) {
+			ssize_t len = read(pty, buf, sizeof(buf));
+			if (len < 0) err(EX_IOERR, "read");
+			if (!len) break;
+
+			len = write(STDOUT_FILENO, buf, len);
+			if (len < 0) err(EX_IOERR, "write");
+		}
+	}
+}
+
+int main(int argc, char *argv[]) {
+	int error;
+
+	bool atch = false;
+	bool sink = false;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "as"))) {
+		switch (opt) {
+			break; case 'a': atch = true;
+			break; case 's': sink = true;
+			break; default:  return EX_USAGE;
+		}
+	}
+	if (optind == argc) errx(EX_USAGE, "no session name");
+	const char *name = argv[optind++];
+
+	if (optind == argc) {
+		argv[--optind] = getenv("SHELL");
+		if (!argv[optind]) errx(EX_CONFIG, "SHELL unset");
+	}
+
+	const char *home = getenv("HOME");
+	if (!home) errx(EX_CONFIG, "HOME unset");
+
+	int fd = open(home, 0);
+	if (fd < 0) err(EX_CANTCREAT, "%s", home);
+
+	error = mkdirat(fd, ".dtch", 0700);
+	if (error && errno != EEXIST) err(EX_CANTCREAT, "%s/.dtch", home);
+
+	close(fd);
+
+	int sock = socket(PF_UNIX, SOCK_STREAM, 0);
+	if (sock < 0) err(EX_OSERR, "socket");
+	fcntl(sock, F_SETFD, FD_CLOEXEC);
+
+	snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.dtch/%s", home, name);
+
+	if (atch) {
+		error = connect(sock, (struct sockaddr *)&addr, SUN_LEN(&addr));
+		if (error) err(EX_NOINPUT, "%s", addr.sun_path);
+		attach(sock);
+	} else {
+		error = bind(sock, (struct sockaddr *)&addr, SUN_LEN(&addr));
+		if (error) err(EX_CANTCREAT, "%s", addr.sun_path);
+		detach(sock, sink, &argv[optind]);
+	}
+}
diff --git a/bin/ever.c b/bin/ever.c
new file mode 100644
index 00000000..f8ff943b
--- /dev/null
+++ b/bin/ever.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2017  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/event.h>
+#include <sys/wait.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static int watch(int kq, char *path) {
+	int fd = open(path, O_CLOEXEC);
+	if (fd < 0) err(EX_NOINPUT, "%s", path);
+
+	struct kevent event;
+	EV_SET(
+		&event,
+		fd,
+		EVFILT_VNODE,
+		EV_ADD | EV_CLEAR,
+		NOTE_WRITE | NOTE_DELETE,
+		0,
+		path
+	);
+	int nevents = kevent(kq, &event, 1, NULL, 0, NULL);
+	if (nevents < 0) err(EX_OSERR, "kevent");
+
+	return fd;
+}
+
+static bool quiet;
+static void exec(int fd, char *const argv[]) {
+	pid_t pid = fork();
+	if (pid < 0) err(EX_OSERR, "fork");
+
+	if (!pid) {
+		dup2(fd, STDIN_FILENO);
+		execvp(*argv, argv);
+		err(EX_NOINPUT, "%s", *argv);
+	}
+
+	int status;
+	pid = wait(&status);
+	if (pid < 0) err(EX_OSERR, "wait");
+
+	if (quiet) return;
+	if (WIFEXITED(status)) {
+		warnx("exit %d\n", WEXITSTATUS(status));
+	} else if (WIFSIGNALED(status)) {
+		warnx("signal %d\n", WTERMSIG(status));
+	} else {
+		warnx("status %d\n", status);
+	}
+}
+
+int main(int argc, char *argv[]) {
+	bool input = false;
+
+	for (int opt; 0 < (opt = getopt(argc, argv, "iq"));) {
+		switch (opt) {
+			break; case 'i': input = true;
+			break; case 'q': quiet = true;
+			break; default:  return EX_USAGE;
+		}
+	}
+	argc -= optind;
+	argv += optind;
+	if (argc < 2) return EX_USAGE;
+
+	int kq = kqueue();
+	if (kq < 0) err(EX_OSERR, "kqueue");
+
+	int i;
+	for (i = 0; i < argc - 1; ++i) {
+		if (argv[i][0] == '-') {
+			i++;
+			break;
+		}
+		watch(kq, argv[i]);
+	}
+
+	if (!input) {
+		exec(STDIN_FILENO, &argv[i]);
+	}
+
+	for (;;) {
+		struct kevent event;
+		int nevents = kevent(kq, NULL, 0, &event, 1, NULL);
+		if (nevents < 0) err(EX_OSERR, "kevent");
+
+		if (event.fflags & NOTE_DELETE) {
+			close(event.ident);
+			sleep(1);
+			event.ident = watch(kq, (char *)event.udata);
+		} else if (input) {
+			off_t off = lseek(event.ident, 0, SEEK_SET);
+			if (off < 0) err(EX_IOERR, "lseek");
+		}
+
+		exec((input ? event.ident : STDIN_FILENO), &argv[i]);
+	}
+}
diff --git a/bin/fbatt.c b/bin/fbatt.c
new file mode 100644
index 00000000..8b7e6e40
--- /dev/null
+++ b/bin/fbatt.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "scheme.h"
+
+static const char *Class = "/sys/class/power_supply";
+
+static const uint32_t Right  = 5 * 8 + 1; // fbclock width.
+static const uint32_t Width  = 8;
+static const uint32_t Height = 16;
+
+int main() {
+	int error;
+
+	DIR *dir = opendir(Class);
+	if (!dir) err(EX_OSFILE, "%s", Class);
+
+	FILE *chargeFull = NULL;
+	FILE *chargeNow = NULL;
+
+	const struct dirent *entry;
+	while (NULL != (errno = 0, entry = readdir(dir))) {
+		if (entry->d_name[0] == '.') continue;
+
+		error = chdir(Class);
+		if (error) err(EX_OSFILE, "%s", Class);
+
+		error = chdir(entry->d_name);
+		if (error) err(EX_OSFILE, "%s/%s", Class, entry->d_name);
+
+		chargeFull = fopen("charge_full", "r");
+		chargeNow = fopen("charge_now", "r");
+		if (chargeFull && chargeNow) break;
+	}
+	if (!chargeFull || !chargeNow) {
+		if (errno) err(EX_OSFILE, "%s", Class);
+		errx(EX_CONFIG, "%s: empty", Class);
+	}
+	closedir(dir);
+
+	const char *path = getenv("FRAMEBUFFER");
+	if (!path) path = "/dev/fb0";
+
+	int fb = open(path, O_RDWR);
+	if (fb < 0) err(EX_OSFILE, "%s", path);
+
+	struct fb_var_screeninfo info;
+	error = ioctl(fb, FBIOGET_VSCREENINFO, &info);
+	if (error) err(EX_IOERR, "%s", path);
+
+	size_t size = 4 * info.xres * info.yres;
+	uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
+	if (buf == MAP_FAILED) err(EX_IOERR, "%s", path);
+
+	for (;;) {
+		int match;
+
+		rewind(chargeFull);
+		fflush(chargeFull);
+		uint32_t full;
+		match = fscanf(chargeFull, "%u", &full);
+		if (match == EOF) err(EX_IOERR, "charge_full");
+		if (match < 1) errx(EX_DATAERR, "charge_full");
+
+		rewind(chargeNow);
+		fflush(chargeNow);
+		uint32_t now;
+		match = fscanf(chargeNow, "%u", &now);
+		if (match == EOF) err(EX_IOERR, "charge_now");
+		if (match < 1) errx(EX_DATAERR, "charge_now");
+
+		uint32_t percent = 100 * now / full;
+		uint32_t height = 16 * now / full;
+
+		for (int i = 0; i < 60; ++i, sleep(1)) {
+			uint32_t left = info.xres - Right - Width;
+
+			for (uint32_t y = 0; y <= Height; ++y) {
+				buf[y * info.xres + left - 1] = DarkWhite;
+				buf[y * info.xres + left + Width] = DarkWhite;
+			}
+			for (uint32_t x = left; x < left + Width; ++x) {
+				buf[Height * info.xres + x] = DarkWhite;
+			}
+
+			for (uint32_t y = 0; y < Height; ++y) {
+				for (uint32_t x = left; x < left + Width; ++x) {
+					buf[y * info.xres + x] =
+						(Height - 1 - y > height) ? DarkBlack
+						: (percent <= 10) ? DarkRed
+						: (percent <= 30) ? DarkYellow
+						: LightBlack;
+				}
+			}
+		}
+	}
+}
diff --git a/bin/fbclock.c b/bin/fbclock.c
new file mode 100644
index 00000000..e1e418b9
--- /dev/null
+++ b/bin/fbclock.c
@@ -0,0 +1,132 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <fcntl.h>
+#include <linux/fb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include "scheme.h"
+
+static const uint32_t PSF2Magic = 0x864AB572;
+struct PSF2Header {
+	uint32_t magic;
+	uint32_t version;
+	uint32_t headerSize;
+	uint32_t flags;
+	uint32_t glyphCount;
+	uint32_t glyphSize;
+	uint32_t glyphHeight;
+	uint32_t glyphWidth;
+};
+
+int main() {
+	size_t len;
+
+	const char *fontPath = getenv("FONT");
+	if (!fontPath) {
+		fontPath = "/usr/share/kbd/consolefonts/Lat2-Terminus16.psfu.gz";
+	}
+
+	gzFile font = gzopen(fontPath, "r");
+	if (!font) err(EX_NOINPUT, "%s", fontPath);
+
+	struct PSF2Header header;
+	len = gzfread(&header, sizeof(header), 1, font);
+	if (!len && gzeof(font)) errx(EX_DATAERR, "%s: missing header", fontPath);
+	if (!len) errx(EX_IOERR, "%s", gzerror(font, NULL));
+
+	if (header.magic != PSF2Magic) {
+		errx(
+			EX_DATAERR, "%s: invalid header magic %08X",
+			fontPath, header.magic
+		);
+	}
+	if (header.headerSize != sizeof(struct PSF2Header)) {
+		errx(
+			EX_DATAERR, "%s: weird header size %d",
+			fontPath, header.headerSize
+		);
+	}
+
+	uint8_t glyphs[128][header.glyphSize];
+	len = gzfread(glyphs, header.glyphSize, 128, font);
+	if (!len && gzeof(font)) errx(EX_DATAERR, "%s: missing glyphs", fontPath);
+	if (!len) errx(EX_IOERR, "%s", gzerror(font, NULL));
+
+	gzclose(font);
+
+	const char *fbPath = getenv("FRAMEBUFFER");
+	if (!fbPath) fbPath = "/dev/fb0";
+
+	int fb = open(fbPath, O_RDWR);
+	if (fb < 0) err(EX_OSFILE, "%s", fbPath);
+
+	struct fb_var_screeninfo info;
+	int error = ioctl(fb, FBIOGET_VSCREENINFO, &info);
+	if (error) err(EX_IOERR, "%s", fbPath);
+
+	size_t size = 4 * info.xres * info.yres;
+	uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
+	if (buf == MAP_FAILED) err(EX_IOERR, "%s", fbPath);
+
+	for (;;) {
+		time_t t = time(NULL);
+		if (t < 0) err(EX_OSERR, "time");
+		const struct tm *local = localtime(&t);
+		if (!local) err(EX_OSERR, "localtime");
+
+		char str[64];
+		len = strftime(str, sizeof(str), "%H:%M", local);
+		assert(len);
+
+		for (int i = 0; i < (60 - local->tm_sec); ++i, sleep(1)) {
+			uint32_t left = info.xres - header.glyphWidth * len;
+			uint32_t bottom = header.glyphHeight;
+
+			for (uint32_t y = 0; y < bottom; ++y) {
+				buf[y * info.xres + left - 1] = DarkWhite;
+			}
+			for (uint32_t x = left - 1; x < info.xres; ++x) {
+				buf[bottom * info.xres + x] = DarkWhite;
+			}
+
+			for (const char *s = str; *s; ++s) {
+				const uint8_t *glyph = glyphs[(unsigned)*s];
+				uint32_t stride = header.glyphSize / header.glyphHeight;
+				for (uint32_t y = 0; y < header.glyphHeight; ++y) {
+					for (uint32_t x = 0; x < header.glyphWidth; ++x) {
+						uint8_t bits = glyph[y * stride + x / 8];
+						uint8_t bit = bits >> (7 - x % 8) & 1;
+						buf[y * info.xres + left + x] = bit
+							? DarkWhite
+							: DarkBlack;
+					}
+				}
+				left += header.glyphWidth;
+			}
+		}
+	}
+}
diff --git a/bin/freecell.c b/bin/freecell.c
new file mode 100644
index 00000000..fbc0fe22
--- /dev/null
+++ b/bin/freecell.c
@@ -0,0 +1,388 @@
+/* Copyright (C) 2019, 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <curses.h>
+#include <err.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+typedef unsigned uint;
+typedef unsigned char byte;
+
+typedef byte Card;
+enum {
+	A = 1,
+	J = 11,
+	Q = 12,
+	K = 13,
+	Rank = 0x0F,
+	Suit = 0x30,
+	Color = 0x10,
+	Club = 0x00,
+	Diamond = 0x10,
+	Spade = 0x20,
+	Heart = 0x30,
+};
+
+enum { StackCap = 52 };
+struct Stack {
+	byte len;
+	Card cards[StackCap];
+};
+static void push(struct Stack *stack, Card card) {
+	assert(stack->len < StackCap);
+	stack->cards[stack->len++] = card;
+}
+static Card pop(struct Stack *stack) {
+	if (!stack->len) return 0;
+	return stack->cards[--stack->len];
+}
+static Card peek(struct Stack *stack) {
+	if (!stack->len) return 0;
+	return stack->cards[stack->len-1];
+}
+
+enum {
+	Foundation,
+	Cell = Foundation + 4,
+	Tableau = Cell + 4,
+	Stacks = Tableau + 8,
+};
+static struct Stack stacks[Stacks];
+
+struct Move {
+	byte dst;
+	byte src;
+};
+
+enum { QCap = 16 };
+static struct {
+	struct Move moves[QCap];
+	uint r, w, u;
+} q;
+static void enq(byte dst, byte src) {
+	q.moves[q.w % QCap].dst = dst;
+	q.moves[q.w % QCap].src = src;
+	q.w++;
+}
+static void deq(void) {
+	struct Move move = q.moves[q.r++ % QCap];
+	push(&stacks[move.dst], pop(&stacks[move.src]));
+}
+static void undo(void) {
+	uint len = q.w - q.u;
+	if (!len || len > QCap) return;
+	for (uint i = len-1; i < len; --i) {
+		struct Move move = q.moves[(q.u+i) % QCap];
+		push(&stacks[move.src], pop(&stacks[move.dst]));
+	}
+	q.r = q.w = q.u;
+}
+
+// https://rosettacode.org/wiki/Deal_cards_for_FreeCell
+static uint lcgState;
+static uint lcg(void) {
+	lcgState = (214013 * lcgState + 2531011) % (1 << 31);
+	return lcgState >> 16;
+}
+static void deal(uint game) {
+	lcgState = game;
+	struct Stack deck = {0};
+	for (Card i = A; i <= K; ++i) {
+		push(&deck, Club | i);
+		push(&deck, Diamond | i);
+		push(&deck, Heart | i);
+		push(&deck, Spade | i);
+	}
+	for (uint stack = 0; deck.len; ++stack) {
+		uint i = lcg() % deck.len;
+		Card card = deck.cards[i];
+		deck.cards[i] = deck.cards[--deck.len];
+		push(&stacks[Tableau + stack%8], card);
+	}
+}
+
+static bool win(void) {
+	for (uint i = Foundation; i < Cell; ++i) {
+		if (stacks[i].len != 13) return false;
+	}
+	return true;
+}
+
+static bool valid(uint dst, Card card) {
+	Card top = peek(&stacks[dst]);
+	if (dst < Cell) {
+		if (!top) return (card & Rank) == A;
+		return (card & Suit) == (top & Suit)
+			&& (card & Rank) == (top & Rank) + 1;
+	}
+	if (!top) return true;
+	if (dst >= Tableau) {
+		return (card & Color) != (top & Color)
+			&& (card & Rank) == (top & Rank) - 1;
+	}
+	return false;
+}
+
+static void autoEnq(void) {
+	Card min[] = { K, K };
+	for (uint i = Cell; i < Stacks; ++i) {
+		for (uint j = 0; j < stacks[i].len; ++j) {
+			Card card = stacks[i].cards[j];
+			if ((card & Rank) < min[!!(card & Color)]) {
+				min[!!(card & Color)] = card & Rank;
+			}
+		}
+	}
+	for (uint src = Cell; src < Stacks; ++src) {
+		Card card = peek(&stacks[src]);
+		if (!card) continue;
+		if (min[!(card & Color)] < (card & Rank)-1) continue;
+		for (uint dst = Foundation; dst < Cell; ++dst) {
+			if (valid(dst, card)) {
+				enq(dst, src);
+				return;
+			}
+		}
+	}
+}
+
+static void moveSingle(uint dst, uint src) {
+	if (!valid(dst, peek(&stacks[src]))) return;
+	q.u = q.w;
+	enq(dst, src);
+}
+
+static uint freeCells(uint cells[static 4]) {
+	uint len = 0;
+	for (uint i = Cell; i < Tableau; ++i) {
+		if (!stacks[i].len) cells[len++] = i;
+	}
+	return len;
+}
+
+static uint moveDepth(uint src) {
+	struct Stack stack = stacks[src];
+	if (stack.len < 2) return stack.len;
+	uint n = 1;
+	for (uint i = stack.len-2; i < stack.len; --i, ++n) {
+		if ((stack.cards[i] & Color) == (stack.cards[i+1] & Color)) break;
+		if ((stack.cards[i] & Rank) != (stack.cards[i+1] & Rank) + 1) break;
+	}
+	return n;
+}
+
+static void moveColumn(uint dst, uint src) {
+	uint depth;
+	uint cells[4];
+	uint free = freeCells(cells);
+	for (depth = moveDepth(src); depth; --depth) {
+		if (free < depth-1) continue;
+		if (valid(dst, stacks[src].cards[stacks[src].len-depth])) break;
+	}
+	if (depth < 2 || dst < Tableau) {
+		moveSingle(dst, src);
+		return;
+	}
+	q.u = q.w;
+	for (uint i = 0; i < depth-1; ++i) {
+		enq(cells[i], src);
+	}
+	enq(dst, src);
+	for (uint i = depth-2; i < depth-1; --i) {
+		enq(dst, cells[i]);
+	}
+}
+
+static void curse(void) {
+	setlocale(LC_CTYPE, "");
+	initscr();
+	cbreak();
+	noecho();
+	curs_set(0);
+	start_color();
+	use_default_colors();
+	init_pair(1, COLOR_BLACK, COLOR_WHITE);
+	init_pair(2, COLOR_RED, COLOR_WHITE);
+	init_pair(3, COLOR_GREEN, -1);
+}
+
+static void drawCard(bool hi, int y, int x, Card card) {
+	if (!card) return;
+	move(y, x);
+	attr_set(hi ? A_REVERSE : A_NORMAL, (card & Color) ? 2 : 1, NULL);
+	switch (card & Suit) {
+		break; case Club: addstr("\u2663");
+		break; case Diamond: addstr("\u2666");
+		break; case Spade: addstr("\u2660");
+		break; case Heart: addstr("\u2665");
+		break; default:;
+	}
+	switch (card & Rank) {
+		break; case A: addstr(" A");
+		break; case 10: addstr("10");
+		break; case J: addstr(" J");
+		break; case Q: addstr(" Q");
+		break; case K: addstr(" K");
+		break; default: {
+			addch(' ');
+			addch('0' + (card & Rank));
+		}
+	}
+	attr_set(A_NORMAL, 0, NULL);
+}
+
+static void drawStack(bool hi, int y, int x, const struct Stack *stack) {
+	for (uint i = 0; i < stack->len; ++i) {
+		drawCard(hi && i == stack->len-1, y++, x, stack->cards[i]);
+	}
+}
+
+enum {
+	Padding = 1,
+	CardWidth = 3,
+	CardHeight = 1,
+	CellX = Padding,
+	CellY = 2*CardHeight,
+	FoundationX = CellX + 4*(CardWidth+Padding),
+	FoundationY = CellY,
+	TableauX = CellX,
+	TableauY = CellY + 2*CardHeight,
+};
+
+static uint game;
+static uint srcStack = Stacks;
+
+static void draw(void) {
+	erase();
+	static char buf[256];
+	if (!buf[0]) snprintf(buf, sizeof(buf), "Game #%u", game);
+	attr_set(A_NORMAL, 3, NULL);
+	mvaddstr(0, Padding, buf);
+	for (uint i = 0; i < Stacks; ++i) {
+		int y, x;
+		char key;
+		if (i < Cell) {
+			y = FoundationY;
+			x = FoundationX + (3-(i-Foundation)) * (CardWidth+Padding);
+			key = '_';
+		} else if (i < Tableau) {
+			y = CellY;
+			x = CellX + (i-Cell) * (CardWidth+Padding);
+			key = '1' + i-Cell;
+		} else {
+			y = TableauY;
+			x = TableauX + (i-Tableau) * (CardWidth+Padding);
+			key = "QWERASDF"[i-Tableau];
+		}
+		if (i < Tableau) {
+			mvaddch(y, x+1, COLOR_PAIR(3) | key);
+		} else {
+			mvaddch(y + 8*CardHeight, x+1, COLOR_PAIR(3) | key);
+		}
+		if (i < Cell) {
+			drawCard(false, y, x, peek(&stacks[i]));
+		} else {
+			drawStack(i == srcStack, y, x, &stacks[i]);
+		}
+	}
+}
+
+static void input(void) {
+	char ch = getch();
+	uint stack = Stacks;
+	switch (tolower(ch)) {
+		break; case '\33': srcStack = Stacks;
+		break; case 'u': case '\b': case '\177': undo();
+		break; case '1': case '!': stack = Cell+0;
+		break; case '2': case '@': stack = Cell+1;
+		break; case '3': case '#': stack = Cell+2;
+		break; case '4': case '$': stack = Cell+3;
+		break; case '_': case ' ': stack = Foundation;
+		break; case 'q': stack = Tableau+0;
+		break; case 'w': stack = Tableau+1;
+		break; case 'e': stack = Tableau+2;
+		break; case 'r': stack = Tableau+3;
+		break; case 'a': stack = Tableau+4;
+		break; case 's': stack = Tableau+5;
+		break; case 'd': stack = Tableau+6;
+		break; case 'f': stack = Tableau+7;
+	}
+	if (stack == Stacks) return;
+
+	if (srcStack < Stacks) {
+		Card card = peek(&stacks[srcStack]);
+		if (stack == Foundation) {
+			for (; stack < Cell; ++stack) {
+				if (valid(stack, card)) break;
+			}
+			if (stack == Cell) return;
+		}
+		if (stack == srcStack) {
+			for (stack = Cell; stack < Stacks; ++stack) {
+				if (!stacks[stack].len) break;
+			}
+			if (stack == Stacks) return;
+		}
+		if (isupper(ch)) {
+			moveSingle(stack, srcStack);
+		} else {
+			moveColumn(stack, srcStack);
+		}
+		srcStack = Stacks;
+
+	} else if (stack >= Cell && stacks[stack].len) {
+		srcStack = stack;
+	}
+}
+
+static void status(void) {
+	printf("Game #%u %s!\n", game, win() ? "win" : "lose");
+}
+
+int main(int argc, char *argv[]) {
+	game = 1 + time(NULL) % 32000;
+	uint delay = 50;
+	for (int opt; 0 < (opt = getopt(argc, argv, "d:n:"));) {
+		switch (opt) {
+			break; case 'd': delay = strtoul(optarg, NULL, 10);
+			break; case 'n': game = strtoul(optarg, NULL, 10);
+			break; default:  return EX_USAGE;
+		}
+	}
+	curse();
+	deal(game);
+	atexit(status);
+	while (!win()) {
+		while (q.r < q.w) {
+			deq();
+			draw();
+			refresh();
+			usleep(delay * 1000);
+			if (q.r == q.w) autoEnq();
+		}
+		draw();
+		input();
+	}
+	endwin();
+}
diff --git a/bin/glitch.c b/bin/glitch.c
new file mode 100644
index 00000000..acb2615c
--- /dev/null
+++ b/bin/glitch.c
@@ -0,0 +1,538 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arpa/inet.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#define PACKED __attribute__((packed))
+
+#define CRC_INIT (crc32(0, Z_NULL, 0))
+
+static const char *path;
+static FILE *file;
+static uint32_t crc;
+
+static void readExpect(void *ptr, size_t size, const char *expect) {
+	fread(ptr, size, 1, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+	if (feof(file)) errx(EX_DATAERR, "%s: missing %s", path, expect);
+	crc = crc32(crc, ptr, size);
+}
+
+static void writeExpect(const void *ptr, size_t size) {
+	fwrite(ptr, size, 1, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+	crc = crc32(crc, ptr, size);
+}
+
+static const uint8_t Signature[8] = "\x89PNG\r\n\x1A\n";
+
+static void readSignature(void) {
+	uint8_t signature[8];
+	readExpect(signature, 8, "signature");
+	if (0 != memcmp(signature, Signature, 8)) {
+		errx(EX_DATAERR, "%s: invalid signature", path);
+	}
+}
+
+static void writeSignature(void) {
+	writeExpect(Signature, sizeof(Signature));
+}
+
+struct PACKED Chunk {
+	uint32_t size;
+	char type[4];
+};
+
+static const char *typeStr(struct Chunk chunk) {
+	static char buf[5];
+	memcpy(buf, chunk.type, 4);
+	return buf;
+}
+
+static struct Chunk readChunk(void) {
+	struct Chunk chunk;
+	readExpect(&chunk, sizeof(chunk), "chunk");
+	chunk.size = ntohl(chunk.size);
+	crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type));
+	return chunk;
+}
+
+static void writeChunk(struct Chunk chunk) {
+	chunk.size = htonl(chunk.size);
+	writeExpect(&chunk, sizeof(chunk));
+	crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type));
+}
+
+static void readCrc(void) {
+	uint32_t expected = crc;
+	uint32_t found;
+	readExpect(&found, sizeof(found), "CRC32");
+	found = ntohl(found);
+	if (found != expected) {
+		errx(
+			EX_DATAERR, "%s: expected CRC32 %08X, found %08X",
+			path, expected, found
+		);
+	}
+}
+
+static void writeCrc(void) {
+	uint32_t net = htonl(crc);
+	writeExpect(&net, sizeof(net));
+}
+
+static void skipChunk(struct Chunk chunk) {
+	uint8_t discard[chunk.size];
+	readExpect(discard, sizeof(discard), "chunk data");
+	readCrc();
+}
+
+static struct PACKED {
+	uint32_t width;
+	uint32_t height;
+	uint8_t depth;
+	enum PACKED {
+		Grayscale      = 0,
+		Truecolor      = 2,
+		Indexed        = 3,
+		GrayscaleAlpha = 4,
+		TruecolorAlpha = 6,
+	} color;
+	uint8_t compression;
+	uint8_t filter;
+	uint8_t interlace;
+} header;
+_Static_assert(13 == sizeof(header), "header size");
+
+static size_t pixelBits(void) {
+	switch (header.color) {
+		case Grayscale:      return 1 * header.depth;
+		case Truecolor:      return 3 * header.depth;
+		case Indexed:        return 1 * header.depth;
+		case GrayscaleAlpha: return 2 * header.depth;
+		case TruecolorAlpha: return 4 * header.depth;
+		default: abort();
+	}
+}
+
+static size_t pixelSize(void) {
+	return (pixelBits() + 7) / 8;
+}
+
+static size_t lineSize(void) {
+	return (header.width * pixelBits() + 7) / 8;
+}
+
+static size_t dataSize(void) {
+	return (1 + lineSize()) * header.height;
+}
+
+static void readHeader(void) {
+	struct Chunk ihdr = readChunk();
+	if (0 != memcmp(ihdr.type, "IHDR", 4)) {
+		errx(EX_DATAERR, "%s: expected IHDR, found %s", path, typeStr(ihdr));
+	}
+	if (ihdr.size != sizeof(header)) {
+		errx(
+			EX_DATAERR, "%s: expected IHDR size %zu, found %u",
+			path, sizeof(header), ihdr.size
+		);
+	}
+	readExpect(&header, sizeof(header), "header");
+	readCrc();
+	header.width = ntohl(header.width);
+	header.height = ntohl(header.height);
+	if (!header.width) errx(EX_DATAERR, "%s: invalid width 0", path);
+	if (!header.height) errx(EX_DATAERR, "%s: invalid height 0", path);
+}
+
+static void writeHeader(void) {
+	struct Chunk ihdr = { .size = sizeof(header), .type = "IHDR" };
+	writeChunk(ihdr);
+	header.width = htonl(header.width);
+	header.height = htonl(header.height);
+	writeExpect(&header, sizeof(header));
+	writeCrc();
+	header.width = ntohl(header.width);
+	header.height = ntohl(header.height);
+}
+
+static struct {
+	uint32_t len;
+	uint8_t entries[256][3];
+} palette;
+
+static void readPalette(void) {
+	struct Chunk chunk;
+	for (;;) {
+		chunk = readChunk();
+		if (0 == memcmp(chunk.type, "PLTE", 4)) break;
+		skipChunk(chunk);
+	}
+	palette.len = chunk.size / 3;
+	readExpect(palette.entries, chunk.size, "palette data");
+	readCrc();
+}
+
+static void writePalette(void) {
+	struct Chunk plte = { .size = 3 * palette.len, .type = "PLTE" };
+	writeChunk(plte);
+	writeExpect(palette.entries, plte.size);
+	writeCrc();
+}
+
+static uint8_t *data;
+
+static void readData(void) {
+	data = malloc(dataSize());
+	if (!data) err(EX_OSERR, "malloc(%zu)", dataSize());
+
+	struct z_stream_s stream = { .next_out = data, .avail_out = dataSize() };
+	int error = inflateInit(&stream);
+	if (error != Z_OK) errx(EX_SOFTWARE, "%s: inflateInit: %s", path, stream.msg);
+
+	for (;;) {
+		struct Chunk chunk = readChunk();
+		if (0 == memcmp(chunk.type, "IDAT", 4)) {
+			uint8_t *idat = malloc(chunk.size);
+			if (!idat) err(EX_OSERR, "malloc");
+
+			readExpect(idat, chunk.size, "image data");
+			readCrc();
+
+			stream.next_in = idat;
+			stream.avail_in = chunk.size;
+			int error = inflate(&stream, Z_SYNC_FLUSH);
+			free(idat);
+
+			if (error == Z_STREAM_END) break;
+			if (error != Z_OK) errx(EX_DATAERR, "%s: inflate: %s", path, stream.msg);
+
+		} else if (0 == memcmp(chunk.type, "IEND", 4)) {
+			errx(EX_DATAERR, "%s: missing IDAT chunk", path);
+		} else {
+			skipChunk(chunk);
+		}
+	}
+
+	inflateEnd(&stream);
+	if ((size_t)stream.total_out != dataSize()) {
+		errx(
+			EX_DATAERR, "%s: expected data size %zu, found %zu",
+			path, dataSize(), (size_t)stream.total_out
+		);
+	}
+}
+
+static void writeData(void) {
+	uLong size = compressBound(dataSize());
+	uint8_t *deflate = malloc(size);
+	if (!deflate) err(EX_OSERR, "malloc");
+
+	int error = compress2(deflate, &size, data, dataSize(), Z_BEST_SPEED);
+	if (error != Z_OK) errx(EX_SOFTWARE, "%s: compress2: %d", path, error);
+
+	struct Chunk idat = { .size = size, .type = "IDAT" };
+	writeChunk(idat);
+	writeExpect(deflate, size);
+	writeCrc();
+
+	free(deflate);
+}
+
+static void writeEnd(void) {
+	struct Chunk iend = { .size = 0, .type = "IEND" };
+	writeChunk(iend);
+	writeCrc();
+}
+
+enum PACKED Filter {
+	None,
+	Sub,
+	Up,
+	Average,
+	Paeth,
+	FilterCount,
+};
+
+static struct {
+	bool brokenPaeth;
+	bool filt;
+	bool recon;
+	uint8_t declareFilter;
+	uint8_t applyFilter;
+	enum Filter declareFilters[255];
+	enum Filter applyFilters[255];
+	bool invert;
+	bool mirror;
+	bool zeroX;
+	bool zeroY;
+} options;
+
+struct Bytes {
+	uint8_t x;
+	uint8_t a;
+	uint8_t b;
+	uint8_t c;
+};
+
+static uint8_t paethPredictor(struct Bytes f) {
+	int32_t p = (int32_t)f.a + (int32_t)f.b - (int32_t)f.c;
+	int32_t pa = abs(p - (int32_t)f.a);
+	int32_t pb = abs(p - (int32_t)f.b);
+	int32_t pc = abs(p - (int32_t)f.c);
+	if (pa <= pb && pa <= pc) return f.a;
+	if (options.brokenPaeth) {
+		if (pb < pc) return f.b;
+	} else {
+		if (pb <= pc) return f.b;
+	}
+	return f.c;
+}
+
+static uint8_t recon(enum Filter type, struct Bytes f) {
+	switch (type) {
+		case None:    return f.x;
+		case Sub:     return f.x + f.a;
+		case Up:      return f.x + f.b;
+		case Average: return f.x + ((uint32_t)f.a + (uint32_t)f.b) / 2;
+		case Paeth:   return f.x + paethPredictor(f);
+		default:      abort();
+	}
+}
+
+static uint8_t filt(enum Filter type, struct Bytes f) {
+	switch (type) {
+		case None:    return f.x;
+		case Sub:     return f.x - f.a;
+		case Up:      return f.x - f.b;
+		case Average: return f.x - ((uint32_t)f.a + (uint32_t)f.b) / 2;
+		case Paeth:   return f.x - paethPredictor(f);
+		default:      abort();
+	}
+}
+
+static struct Line {
+	enum Filter type;
+	uint8_t data[];
+} **lines;
+
+static void scanlines(void) {
+	lines = calloc(header.height, sizeof(*lines));
+	if (!lines) err(EX_OSERR, "calloc(%u, %zu)", header.height, sizeof(*lines));
+
+	size_t stride = 1 + lineSize();
+	for (uint32_t y = 0; y < header.height; ++y) {
+		lines[y] = (struct Line *)&data[y * stride];
+		if (lines[y]->type >= FilterCount) {
+			errx(EX_DATAERR, "%s: invalid filter type %hhu", path, lines[y]->type);
+		}
+	}
+}
+
+static struct Bytes origBytes(uint32_t y, size_t i) {
+	bool a = (i >= pixelSize()), b = (y > 0), c = (a && b);
+	return (struct Bytes) {
+		.x = lines[y]->data[i],
+		.a = a ? lines[y]->data[i - pixelSize()] : 0,
+		.b = b ? lines[y - 1]->data[i] : 0,
+		.c = c ? lines[y - 1]->data[i - pixelSize()] : 0,
+	};
+}
+
+static void reconData(void) {
+	for (uint32_t y = 0; y < header.height; ++y) {
+		for (size_t i = 0; i < lineSize(); ++i) {
+			if (options.filt) {
+				lines[y]->data[i] = filt(lines[y]->type, origBytes(y, i));
+			} else {
+				lines[y]->data[i] = recon(lines[y]->type, origBytes(y, i));
+			}
+		}
+		lines[y]->type = None;
+	}
+}
+
+static void filterData(void) {
+	for (uint32_t y = header.height - 1; y < header.height; --y) {
+		uint8_t filter[FilterCount][lineSize()];
+		uint32_t heuristic[FilterCount] = {0};
+		enum Filter minType = None;
+		for (enum Filter type = None; type < FilterCount; ++type) {
+			for (size_t i = 0; i < lineSize(); ++i) {
+				if (options.recon) {
+					filter[type][i] = recon(type, origBytes(y, i));
+				} else {
+					filter[type][i] = filt(type, origBytes(y, i));
+				}
+				heuristic[type] += abs((int8_t)filter[type][i]);
+			}
+			if (heuristic[type] < heuristic[minType]) minType = type;
+		}
+
+		if (options.declareFilter) {
+			lines[y]->type = options.declareFilters[y % options.declareFilter];
+		} else {
+			lines[y]->type = minType;
+		}
+
+		if (options.applyFilter) {
+			enum Filter type = options.applyFilters[y % options.applyFilter];
+			memcpy(lines[y]->data, filter[type], lineSize());
+		} else {
+			memcpy(lines[y]->data, filter[minType], lineSize());
+		}
+	}
+}
+
+static void invert(void) {
+	for (uint32_t y = 0; y < header.height; ++y) {
+		for (size_t i = 0; i < lineSize(); ++i) {
+			lines[y]->data[i] ^= 0xFF;
+		}
+	}
+}
+
+static void mirror(void) {
+	for (uint32_t y = 0; y < header.height; ++y) {
+		for (size_t i = 0, j = lineSize() - 1; i < j; ++i, --j) {
+			uint8_t t = lines[y]->data[i];
+			lines[y]->data[i] = lines[y]->data[j];
+			lines[y]->data[j] = t;
+		}
+	}
+}
+
+static void zeroX(void) {
+	for (uint32_t y = 0; y < header.height; ++y) {
+		memset(lines[y]->data, 0, pixelSize());
+	}
+}
+
+static void zeroY(void) {
+	memset(lines[0]->data, 0, lineSize());
+}
+
+static void glitch(const char *inPath, const char *outPath) {
+	if (inPath) {
+		path = inPath;
+		file = fopen(path, "r");
+		if (!file) err(EX_NOINPUT, "%s", path);
+	} else {
+		path = "(stdin)";
+		file = stdin;
+	}
+
+	readSignature();
+	readHeader();
+	if (header.color == Indexed) readPalette();
+	readData();
+	fclose(file);
+
+	scanlines();
+	reconData();
+	filterData();
+	if (options.invert) invert();
+	if (options.mirror) mirror();
+	if (options.zeroX) zeroX();
+	if (options.zeroY) zeroY();
+	free(lines);
+
+	if (outPath) {
+		path = outPath;
+		file = fopen(path, "w");
+		if (!file) err(EX_CANTCREAT, "%s", path);
+	} else {
+		path = "(stdout)";
+		file = stdout;
+	}
+
+	writeSignature();
+	writeHeader();
+	if (header.color == Indexed) writePalette();
+	writeData();
+	writeEnd();
+	free(data);
+
+	int error = fclose(file);
+	if (error) err(EX_IOERR, "%s", path);
+}
+
+static enum Filter parseFilter(const char *s) {
+	switch (s[0]) {
+		case 'N': case 'n': return None;
+		case 'S': case 's': return Sub;
+		case 'U': case 'u': return Up;
+		case 'A': case 'a': return Average;
+		case 'P': case 'p': return Paeth;
+		default: errx(EX_USAGE, "invalid filter type %s", s);
+	}
+}
+
+static uint8_t parseFilters(enum Filter *filters, const char *s) {
+	uint8_t len = 0;
+	do {
+		filters[len++] = parseFilter(s);
+		s = strchr(s, ',');
+	} while (s++);
+	return len;
+}
+
+int main(int argc, char *argv[]) {
+	bool stdio = false;
+	char *output = NULL;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "a:cd:fimo:prxy"))) {
+		switch (opt) {
+			break; case 'a':
+				options.applyFilter = parseFilters(options.applyFilters, optarg);
+			break; case 'c': stdio = true;
+			break; case 'd':
+				options.declareFilter = parseFilters(options.declareFilters, optarg);
+			break; case 'f': options.filt = true;
+			break; case 'i': options.invert = true;
+			break; case 'm': options.mirror = true;
+			break; case 'o': output = optarg;
+			break; case 'p': options.brokenPaeth = true;
+			break; case 'r': options.recon = true;
+			break; case 'x': options.zeroX = true;
+			break; case 'y': options.zeroY = true;
+			break; default: return EX_USAGE;
+		}
+	}
+
+	if (argc - optind == 1 && (output || stdio)) {
+		glitch(argv[optind], output);
+	} else if (optind < argc) {
+		for (int i = optind; i < argc; ++i) {
+			glitch(argv[i], argv[i]);
+		}
+	} else {
+		glitch(NULL, output);
+	}
+
+	return EX_OK;
+}
diff --git a/bin/hilex.c b/bin/hilex.c
new file mode 100644
index 00000000..8a06eb36
--- /dev/null
+++ b/bin/hilex.c
@@ -0,0 +1,391 @@
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "hilex.h"
+
+#define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
+
+static const char *Class[] = {
+#define X(class) [class] = #class,
+	ENUM_CLASS
+#undef X
+};
+
+static FILE *yyin;
+static char *yytext;
+static int yylex(void) {
+	static size_t cap = 0;
+	return (getline(&yytext, &cap, yyin) < 0 ? None : Normal);
+}
+static const struct Lexer LexText = { yylex, &yyin, &yytext };
+
+static const struct {
+	const struct Lexer *lexer;
+	const char *name;
+	const char *namePatt;
+	const char *linePatt;
+} Lexers[] = {
+	{ &LexC, "c", "[.][chlmy]$", NULL },
+	{ &LexMake, "make", "[.](mk|am)$|^Makefile$", NULL },
+	{ &LexMdoc, "mdoc", "[.][1-9]$", "^[.]Dd" },
+	{ &LexSh, "sh", "[.]sh$|^[.](profile|shrc)$", "^#![ ]?/bin/sh" },
+	{ &LexText, "text", "[.]txt$", NULL },
+};
+
+static const struct Lexer *parseLexer(const char *name) {
+	for (size_t i = 0; i < ARRAY_LEN(Lexers); ++i) {
+		if (!strcmp(name, Lexers[i].name)) return Lexers[i].lexer;
+	}
+	errx(EX_USAGE, "unknown lexer %s", name);
+}
+
+static void ungets(const char *str, FILE *file) {
+	size_t len = strlen(str);
+	for (size_t i = len-1; i < len; --i) {
+		int ch = ungetc(str[i], file);
+		if (ch == EOF) errx(EX_IOERR, "cannot push back string");
+	}
+}
+
+static const struct Lexer *matchLexer(const char *name, FILE *file) {
+	char buf[256];
+	regex_t regex;
+	for (size_t i = 0; i < ARRAY_LEN(Lexers); ++i) {
+		int error = regcomp(
+			&regex, Lexers[i].namePatt, REG_EXTENDED | REG_NOSUB
+		);
+		assert(!error);
+		error = regexec(&regex, name, 0, NULL, 0);
+		regfree(&regex);
+		if (!error) return Lexers[i].lexer;
+	}
+	char *line = fgets(buf, sizeof(buf), file);
+	if (!line) return NULL;
+	for (size_t i = 0; i < ARRAY_LEN(Lexers); ++i) {
+		if (!Lexers[i].linePatt) continue;
+		int error = regcomp(
+			&regex, Lexers[i].linePatt, REG_EXTENDED | REG_NOSUB
+		);
+		assert(!error);
+		error = regexec(&regex, line, 0, NULL, 0);
+		regfree(&regex);
+		if (!error) {
+			ungets(line, file);
+			return Lexers[i].lexer;
+		}
+	}
+	ungets(line, file);
+	return NULL;
+}
+
+#define ENUM_OPTION \
+	X(Document, "document") \
+	X(Inline, "inline") \
+	X(Monospace, "monospace") \
+	X(Pre, "pre") \
+	X(Style, "style") \
+	X(Tab, "tab") \
+	X(Title, "title")
+
+enum Option {
+#define X(option, key) option,
+	ENUM_OPTION
+#undef X
+	OptionCap,
+};
+
+typedef void Header(const char *opts[]);
+typedef void Output(const char *opts[], enum Class class, const char *text);
+
+static bool pager;
+static void ansiHeader(const char *opts[]) {
+	(void)opts;
+	if (!pager) return;
+	const char *shell = getenv("SHELL");
+	const char *pager = getenv("PAGER");
+	if (!shell) shell = "/bin/sh";
+	if (!pager) pager = "less";
+	setenv("LESS", "FRX", 0);
+
+	int rw[2];
+	int error = pipe(rw);
+	if (error) err(EX_OSERR, "pipe");
+
+	pid_t pid = fork();
+	if (pid < 0) err(EX_OSERR, "fork");
+	if (!pid) {
+		dup2(rw[0], STDIN_FILENO);
+		close(rw[0]);
+		close(rw[1]);
+		execl(shell, shell, "-c", pager, NULL);
+		err(EX_CONFIG, "%s", shell);
+	}
+	dup2(rw[1], STDOUT_FILENO);
+	close(rw[0]);
+	close(rw[1]);
+	setlinebuf(stdout);
+}
+
+static void ansiFooter(const char *opts[]) {
+	(void)opts;
+	if (!pager) return;
+	int status;
+	fclose(stdout);
+	wait(&status);
+}
+
+static const char *SGR[ClassCap] = {
+	[Keyword] = "37",
+	[Macro]   = "32",
+	[Comment] = "34",
+	[String]  = "36",
+	[Format]  = "36;1;96",
+	[Subst]   = "33",
+};
+
+static void ansiFormat(const char *opts[], enum Class class, const char *text) {
+	(void)opts;
+	if (!SGR[class]) {
+		printf("%s", text);
+		return;
+	}
+	// Set color on each line for piping to less -R:
+	for (const char *nl; (nl = strchr(text, '\n')); text = &nl[1]) {
+		printf("\33[%sm%.*s\33[m\n", SGR[class], (int)(nl - text), text);
+	}
+	if (*text) printf("\33[%sm%s\33[m", SGR[class], text);
+}
+
+static void
+debugFormat(const char *opts[], enum Class class, const char *text) {
+	if (class != Normal) {
+		printf("%s(", Class[class]);
+		ansiFormat(opts, class, text);
+		printf(")");
+	} else {
+		printf("%s", text);
+	}
+}
+
+static const char *IRC[ClassCap] = {
+	[Keyword] = "\00315",
+	[Macro]   = "\0033",
+	[Comment] = "\0032",
+	[String]  = "\00310",
+	[Format]  = "\00311",
+	[Subst]   = "\0037",
+};
+
+static void ircHeader(const char *opts[]) {
+	if (opts[Monospace]) printf("\21");
+}
+
+static const char *stop(const char *text) {
+	return (*text == ',' || isdigit(*text) ? "\2\2" : "");
+}
+
+static void ircFormat(const char *opts[], enum Class class, const char *text) {
+	for (const char *nl; (nl = strchr(text, '\n')); text = &nl[1]) {
+		if (IRC[class]) printf("%s%s", IRC[class], stop(text));
+		printf("%.*s\n", (int)(nl - text), text);
+		if (opts[Monospace]) printf("\21");
+	}
+	if (*text) {
+		if (IRC[class]) {
+			printf("%s%s%s\17", IRC[class], stop(text), text);
+			if (opts[Monospace]) printf("\21");
+		} else {
+			printf("%s", text);
+		}
+	}
+}
+
+static void htmlEscape(const char *text) {
+	while (*text) {
+		switch (*text) {
+			break; case '"': text++; printf("&quot;");
+			break; case '&': text++; printf("&amp;");
+			break; case '<': text++; printf("&lt;");
+		}
+		size_t len = strcspn(text, "\"&<");
+		if (len) fwrite(text, len, 1, stdout);
+		text += len;
+	}
+}
+
+static const char *Styles[ClassCap] = {
+	[Keyword] = "color: dimgray;",
+	[Macro]   = "color: green;",
+	[Comment] = "color: navy;",
+	[String]  = "color: teal;",
+	[Format]  = "color: teal; font-weight: bold;",
+	[Subst]   = "color: olive;",
+};
+
+static void styleTabSize(const char *tab) {
+	printf("-moz-tab-size: ");
+	htmlEscape(tab);
+	printf("; tab-size: ");
+	htmlEscape(tab);
+	printf(";");
+}
+
+static void htmlHeader(const char *opts[]) {
+	if (!opts[Document]) goto body;
+
+	printf("<!DOCTYPE html>\n<title>");
+	if (opts[Title]) htmlEscape(opts[Title]);
+	printf("</title>\n");
+
+	if (opts[Style]) {
+		printf("<link rel=\"stylesheet\" href=\"");
+		htmlEscape(opts[Style]);
+		printf("\">\n");
+	} else if (!opts[Inline]) {
+		printf("<style>\n");
+		if (opts[Tab]) {
+			printf("pre.hilex { ");
+			styleTabSize(opts[Tab]);
+			printf(" }\n");
+		}
+		for (enum Class class = 0; class < ClassCap; ++class) {
+			if (!Styles[class]) continue;
+			printf("pre.hilex .%.2s { %s }\n", Class[class], Styles[class]);
+		}
+		printf("</style>\n");
+	}
+
+body:
+	if ((opts[Document] || opts[Pre]) && opts[Inline] && opts[Tab]) {
+		printf("<pre class=\"hilex\" style=\"");
+		styleTabSize(opts[Tab]);
+		printf("\">");
+	} else if (opts[Document] || opts[Pre]) {
+		printf("<pre class=\"hilex\">");
+	}
+}
+
+static void htmlFooter(const char *opts[]) {
+	if (opts[Document] || opts[Pre]) printf("</pre>");
+	if (opts[Document]) printf("\n");
+}
+
+static void htmlFormat(const char *opts[], enum Class class, const char *text) {
+	if (class != Normal) {
+		if (opts[Inline]) {
+			printf("<span style=\"%s\">", Styles[class] ? Styles[class] : "");
+		} else {
+			printf("<span class=\"%.2s\">", Class[class]);
+		}
+		htmlEscape(text);
+		printf("</span>");
+	} else {
+		htmlEscape(text);
+	}
+}
+
+static const struct Formatter {
+	const char *name;
+	Header *header;
+	Output *format;
+	Header *footer;
+} Formatters[] = {
+	{ "ansi", ansiHeader, ansiFormat, ansiFooter },
+	{ "debug", NULL, debugFormat, NULL },
+	{ "html", htmlHeader, htmlFormat, htmlFooter },
+	{ "irc", ircHeader, ircFormat, NULL },
+};
+
+static const struct Formatter *parseFormatter(const char *name) {
+	for (size_t i = 0; i < ARRAY_LEN(Formatters); ++i) {
+		if (!strcmp(name, Formatters[i].name)) return &Formatters[i];
+	}
+	errx(EX_USAGE, "unknown formatter %s", name);
+}
+
+static char *const OptionKeys[OptionCap + 1] = {
+#define X(option, key) [option] = key,
+	ENUM_OPTION
+#undef X
+	NULL,
+};
+
+int main(int argc, char *argv[]) {
+	bool text = false;
+	const char *name = NULL;
+	const struct Lexer *lexer = NULL;
+	const struct Formatter *formatter = &Formatters[0];
+	const char *opts[OptionCap] = {0};
+
+	for (int opt; 0 < (opt = getopt(argc, argv, "f:l:n:o:t"));) {
+		switch (opt) {
+			break; case 'f': formatter = parseFormatter(optarg);
+			break; case 'l': lexer = parseLexer(optarg);
+			break; case 'n': name = optarg;
+			break; case 'o': {
+				while (*optarg) {
+					char *val;
+					int key = getsubopt(&optarg, OptionKeys, &val);
+					if (key < 0) errx(EX_USAGE, "no such option %s", val);
+					opts[key] = (val ? val : "");
+				}
+			}
+			break; case 't': text = true;
+			break; default:  return EX_USAGE;
+		}
+	}
+
+	const char *path = "(stdin)";
+	FILE *file = stdin;
+	if (optind < argc) {
+		path = argv[optind];
+		file = fopen(path, "r");
+		if (!file) err(EX_NOINPUT, "%s", path);
+		pager = isatty(STDOUT_FILENO);
+	}
+
+	if (!name) {
+		if (NULL != (name = strrchr(path, '/'))) {
+			name++;
+		} else {
+			name = path;
+		}
+	}
+	if (!opts[Title]) opts[Title] = name;
+	if (!lexer) lexer = matchLexer(name, file);
+	if (!lexer && text) lexer = &LexText;
+	if (!lexer) errx(EX_USAGE, "cannot infer lexer for %s", name);
+
+	*lexer->in = file;
+	if (formatter->header) formatter->header(opts);
+	for (enum Class class; None != (class = lexer->lex());) {
+		assert(class < ClassCap);
+		formatter->format(opts, class, *lexer->text);
+	}
+	if (formatter->footer) formatter->footer(opts);
+}
diff --git a/bin/hilex.h b/bin/hilex.h
new file mode 100644
index 00000000..b57fc8cc
--- /dev/null
+++ b/bin/hilex.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#define ENUM_CLASS \
+	X(None) \
+	X(Normal) \
+	X(Operator) \
+	X(Number) \
+	X(Keyword) \
+	X(Ident) \
+	X(Macro) \
+	X(Comment) \
+	X(String) \
+	X(Escape) \
+	X(Format) \
+	X(Subst)
+
+enum Class {
+#define X(class) class,
+	ENUM_CLASS
+#undef X
+	ClassCap,
+};
+
+typedef int Lex(void);
+struct Lexer {
+	Lex *lex;
+	FILE **in;
+	char **text;
+};
+
+extern const struct Lexer LexC;
+extern const struct Lexer LexMake;
+extern const struct Lexer LexMdoc;
+extern const struct Lexer LexSh;
diff --git a/bin/htagml.c b/bin/htagml.c
new file mode 100644
index 00000000..a3a4101d
--- /dev/null
+++ b/bin/htagml.c
@@ -0,0 +1,207 @@
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static char *nomagic(const char *pattern) {
+	char *buf = malloc(2 * strlen(pattern) + 1);
+	if (!buf) err(EX_OSERR, "malloc");
+	char *ptr = buf;
+	for (const char *ch = pattern; *ch; ++ch) {
+		if (strchr(".[*", *ch)) *ptr++ = '\\';
+		*ptr++ = *ch;
+	}
+	*ptr = '\0';
+	return buf;
+}
+
+static size_t escape(bool esc, const char *ptr, size_t len) {
+	if (!esc) {
+		fwrite(ptr, len, 1, stdout);
+		return len;
+	}
+	for (size_t i = 0; i < len; ++i) {
+		switch (ptr[i]) {
+			break; case '&': printf("&amp;");
+			break; case '<': printf("&lt;");
+			break; case '"': printf("&quot;");
+			break; default:  putchar(ptr[i]);
+		}
+	}
+	return len;
+}
+
+static void id(const char *tag) {
+	for (const char *ch = tag; *ch; ++ch) {
+		if (isalnum(*ch) || strchr("-._", *ch)) {
+			putchar(*ch);
+		} else {
+			putchar('_');
+		}
+	}
+}
+
+static char *hstrstr(const char *haystack, const char *needle) {
+	while (haystack) {
+		char *elem = strchr(haystack, '<');
+		char *match = strstr(haystack, needle);
+		if (!match) return NULL;
+		if (!elem || match < elem) return match;
+		haystack = strchr(elem, '>');
+	}
+	return NULL;
+}
+
+int main(int argc, char *argv[]) {
+	bool pre = false;
+	bool pipe = false;
+	bool index = false;
+	const char *tagsFile = "tags";
+	for (int opt; 0 < (opt = getopt(argc, argv, "f:ipx"));) {
+		switch (opt) {
+			break; case 'f': tagsFile = optarg;
+			break; case 'i': pipe = true;
+			break; case 'p': pre = true;
+			break; case 'x': index = true;
+			break; default:  return EX_USAGE;
+		}
+	}
+	if (optind == argc) errx(EX_USAGE, "name required");
+	const char *name = argv[optind];
+
+	FILE *file = fopen(tagsFile, "r");
+	if (!file) err(EX_NOINPUT, "%s", tagsFile);
+
+	size_t len = 0;
+	size_t cap = 256;
+	struct Tag {
+		char *tag;
+		int num;
+		regex_t regex;
+	} *tags = malloc(cap * sizeof(*tags));
+	if (!tags) err(EX_OSERR, "malloc");
+
+	char *buf = NULL;
+	size_t bufCap = 0;
+	while (0 < getline(&buf, &bufCap, file)) {
+		char *line = buf;
+		char *tag = strsep(&line, "\t");
+		char *file = strsep(&line, "\t");
+		char *def = strsep(&line, "\n");
+		if (!tag || !file || !def) errx(EX_DATAERR, "malformed tags file");
+
+		if (strcmp(file, name)) continue;
+		if (len == cap) {
+			tags = realloc(tags, (cap *= 2) * sizeof(*tags));
+			if (!tags) err(EX_OSERR, "realloc");
+		}
+		tags[len].tag = strdup(tag);
+		if (!tags[len].tag) err(EX_OSERR, "strdup");
+
+		tags[len].num = 0;
+		if (def[0] == '/' || def[0] == '?') {
+			def++;
+			def[strlen(def)-1] = '\0';
+			char *search = nomagic(def);
+			int error = regcomp(
+				&tags[len].regex, search, REG_NEWLINE | REG_NOSUB
+			);
+			free(search);
+			if (error) {
+				warnx("invalid regex for tag %s: %s", tag, def);
+				continue;
+			}
+		} else {
+			tags[len].num = strtol(def, &def, 10);
+			if (*def) {
+				warnx("invalid line number for tag %s: %s", tag, def);
+				continue;
+			}
+		}
+		len++;
+	}
+	fclose(file);
+
+	file = fopen(name, "r");
+	if (!file) err(EX_NOINPUT, "%s", name);
+
+	int num = 0;
+	printf(pre ? "<pre>" : index ? "<ul class=\"index\">\n" : "");
+	while (0 < getline(&buf, &bufCap, file) && ++num) {
+		struct Tag *tag = NULL;
+		for (size_t i = 0; i < len; ++i) {
+			if (tags[i].num) {
+				if (num != tags[i].num) continue;
+			} else {
+				if (regexec(&tags[i].regex, buf, 0, NULL, 0)) continue;
+			}
+			tag = &tags[i];
+			tag->num = num;
+			break;
+		}
+		if (index) {
+			if (!tag) continue;
+			printf("<li><a class=\"tag\" href=\"#");
+			id(tag->tag);
+			printf("\">");
+			escape(true, tag->tag, strlen(tag->tag));
+			printf("</a></li>\n");
+			continue;
+		}
+		if (pipe) {
+			ssize_t len = getline(&buf, &bufCap, stdin);
+			if (len < 0) {
+				errx(EX_DATAERR, "missing line %d on standard input", num);
+			}
+		}
+		if (!tag) {
+			escape(!pipe, buf, strlen(buf));
+			continue;
+		}
+
+		size_t mlen = strlen(tag->tag);
+		char *match = (pipe ? hstrstr : strstr)(buf, tag->tag);
+		while (match > buf && isalnum(match[-1])) {
+			match = (pipe ? hstrstr : strstr)(&match[mlen], tag->tag);
+		}
+		if (!match && tag->tag[0] == 'M') {
+			mlen = 4;
+			match = (pipe ? hstrstr : strstr)(buf, "main");
+		}
+		if (!match) {
+			mlen = strlen(buf) - 1;
+			match = buf;
+		}
+		escape(!pipe, buf, match - buf);
+		printf("<a class=\"tag\" id=\"");
+		id(tag->tag);
+		printf("\" href=\"#");
+		id(tag->tag);
+		printf("\">");
+		match += escape(!pipe, match, mlen);
+		printf("</a>");
+		escape(!pipe, match, strlen(match));
+	}
+	printf(pre ? "</pre>" : index ? "</ul>\n" : "");
+}
diff --git a/bin/html.mk b/bin/html.mk
new file mode 100644
index 00000000..15e5257a
--- /dev/null
+++ b/bin/html.mk
@@ -0,0 +1,45 @@
+WEBROOT ?= /usr/local/www/causal.agency
+
+HTMLS = index.html png.html
+HTMLS += ${BINS:=.html}
+HTMLS += ${BSD:=.html}
+HTMLS += ${GAMES:=.html}
+HTMLS += ${LINUX:=.html}
+HTMLS += ${TLS:=.html}
+
+html: ${HTMLS}
+	@true
+
+install-html: ${HTMLS}
+	install -d ${WEBROOT}/bin
+	install -C -m 644 ${HTMLS} ${WEBROOT}/bin
+
+${HTMLS}: html.sh scheme hilex htagml htmltags
+
+htmltags: *.[chly] mtags Makefile html.mk *.sh
+	rm -f $@
+	for f in *.[chly]; do ctags -aw -f $@ $$f; done
+	./mtags -a -f $@ Makefile html.mk *.sh
+
+index.html: README.7 Makefile html.mk html.sh
+	sh html.sh README.7 Makefile html.mk html.sh > $@
+
+.SUFFIXES: .html
+
+.c.html:
+	sh html.sh man1/${<:.c=.1} $< > $@
+
+.h.html:
+	sh html.sh man3/${<:.h=.3} $< > $@
+
+.y.html:
+	sh html.sh man1/${<:.y=.1} $< > $@
+
+.sh.html:
+	sh html.sh man1/${<:.sh=.1} $< > $@
+
+.pl.html:
+	sh html.sh man1/${<:.pl=.1} $< > $@
+
+freecell.html: freecell.c man6/freecell.6
+	sh html.sh man6/freecell.6 freecell.c > $@
diff --git a/bin/html.sh b/bin/html.sh
new file mode 100644
index 00000000..d76fcc8c
--- /dev/null
+++ b/bin/html.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+set -eu
+
+readonly GitURL='https://git.causal.agency/src/tree/bin'
+
+man=$1
+shift
+title=${man##*/}
+title=${title%.[1-9]}
+
+cat <<EOF
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>${title}</title>
+<style>
+html { line-height: 1.25em; font-family: monospace; }
+body { max-width: 80ch; margin: 1em auto; padding: 0 1ch; }
+
+table.head, table.foot { width: 100%; }
+td.head-rtitle, td.foot-os { text-align: right; }
+td.head-vol { text-align: center; }
+div.Pp { margin: 1ex 0ex; }
+div.Nd, div.Bf, div.Op { display: inline; }
+span.Pa, span.Ad { font-style: italic; }
+span.Ms { font-weight: bold; }
+dl.Bl-diag > dt { font-weight: bold; }
+code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn,
+code.Cd { font-weight: bold; font-family: inherit; }
+
+table { border-collapse: collapse; }
+table.Nm code.Nm { padding-right: 1ch; }
+table.foot { margin-top: 1em; }
+
+ul.index { padding: 0; }
+ul.index li { display: inline; list-style-type: none; }
+pre { -moz-tab-size: 4; tab-size: 4; }
+
+$(./scheme -st)
+html { background-color: var(--ansi16); color: var(--ansi17); }
+a { color: var(--ansi4); }
+a:visited { color: var(--ansi5); }
+a.permalink, a.tag { color: var(--ansi3); text-decoration: none; }
+a.permalink > code:target, *:target > a.permalink,
+a.tag:target { color: var(--ansi11); }
+pre .Ke { color: var(--ansi7); }
+pre .Ma { color: var(--ansi2); }
+pre .Co { color: var(--ansi4); }
+pre .St { color: var(--ansi6); }
+pre .Fo { color: var(--ansi14); }
+pre .Su { color: var(--ansi1); }
+</style>
+EOF
+
+opts=fragment
+[ "${man}" = "README.7" ] && opts=${opts},man=%N.html
+mandoc -T html -O ${opts} "${man}"
+
+for src; do
+	cat <<-EOF
+	<p>
+	<a href="${GitURL}/${src}">${src} in git</a>
+	EOF
+	./htagml -x -f htmltags "${src}"
+	./hilex -t -f html "${src}" | ./htagml -ip -f htmltags "${src}"
+done
diff --git a/bin/make.l b/bin/make.l
new file mode 100644
index 00000000..6d0c73f9
--- /dev/null
+++ b/bin/make.l
@@ -0,0 +1,132 @@
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%option prefix="make"
+%option noyywrap
+
+%{
+#include "hilex.h"
+%}
+
+%s Assign Preproc
+%x Variable Shell
+
+ident [._[:alnum:]]+
+assign [+?:!]?=
+target [-._/?*\[\][:alnum:]]+
+operator [:!]|::
+
+%%
+	static int pop = INITIAL;
+	static int depth = 0;
+
+^"\t"+ {
+	BEGIN(pop = Shell);
+	return Normal;
+}
+<Shell>{
+	"\n" {
+		BEGIN(pop = INITIAL);
+		return Normal;
+	}
+	"\\\n" { return Normal; }
+	[^\\\n$]+|. { return Normal; }
+}
+
+[[:blank:]]+ { return Normal; }
+
+{operator} { return Operator; }
+
+"."(PHONY|PRECIOUS|SUFFIXES)/{operator}? {
+	return Keyword;
+}
+
+{target}/{operator} { return Ident; }
+
+^"."{ident} |
+^"-"?include {
+	BEGIN(pop = Preproc);
+	return Macro;
+}
+<Preproc>{
+	"\n" {
+		BEGIN(pop = INITIAL);
+		return Normal;
+	}
+	"\\\n""\t"? { return Normal; }
+
+	"\""[^""]*"\"" |
+	"<"[^>]*">" {
+		return String;
+	}
+
+	[!<>=]"="?|"||"|"&&" { return Operator; }
+	[0-9]+|"0x"[[:xdigit:]]+ { return Number; }
+	defined|make|empty|exists|target|commands|in { return Keyword; }
+}
+
+^{ident}/[[:blank:]]*{assign} {
+	return Ident;
+}
+
+{assign} {
+	BEGIN(pop = Assign);
+	return Operator;
+}
+<Assign>{
+	"\n" {
+		BEGIN(pop = INITIAL);
+		return Normal;
+	}
+	"\\\n""\t"? { return Escape; }
+	[^\\$[:space:]]+|. { return String; }
+}
+
+{target} { return Ident; }
+
+"#"([^\\\n]|"\\"[^\n]|"\\\n")* { return Comment; }
+
+<*>{
+	"$"("{"|"(")/[^$] {
+		depth++;
+		BEGIN(Variable);
+		yymore();
+	}
+	"$"("{"|"(") {
+		depth++;
+		BEGIN(Variable);
+		return Subst;
+	}
+	"$". { return Subst; }
+}
+<Variable>{
+	[^${}()]*"}"|")" {
+		if (!--depth) BEGIN(pop);
+		return Subst;
+	}
+	[^${}()]+ { return Subst; }
+}
+
+.|\n { return Normal; }
+
+%{
+	(void)yyunput;
+	(void)input;
+%}
+
+%%
+
+const struct Lexer LexMake = { yylex, &yyin, &yytext };
diff --git a/bin/man1/beef.1 b/bin/man1/beef.1
new file mode 100644
index 00000000..ea52cfa0
--- /dev/null
+++ b/bin/man1/beef.1
@@ -0,0 +1,91 @@
+.Dd August 28, 2019
+.Dt BEEF 1
+.Os
+.
+.Sh NAME
+.Nm beef
+.Nd Befunge-93 interpreter
+.
+.Sh SYNOPSIS
+.Nm
+.Op Ar file
+.
+.Sh DESCRIPTION
+.Nm
+is a Befunge-93 interpreter.
+If no
+.Ar file
+is provided,
+the program is read from standard input.
+.
+.Ss Befunge-93 Command Summary
+.Bl -tag -width "0-9" -compact
+.It \(dq
+toggle string mode
+.It 0-9
+push value
+.It +
+add
+.It -
+subtract
+.It *
+multiply
+.It /
+divide
+.It %
+modulo
+.It !
+not
+.It `
+greater than
+.It >
+right
+.It <
+left
+.It ^
+up
+.It v
+down
+.It ?
+random
+.It _
+horizontal (left) if
+.It |
+vertical (up) if
+.It :
+duplicate
+.It \e
+swap
+.It $
+drop
+.It .
+output integer
+.It ,
+output ASCII
+.It #
+bridge
+.It g
+get (y, x)
+.It p
+put (y, x) = v
+.It &
+input integer
+.It ~
+input ASCII
+.It @
+exit
+.El
+.
+.Sh EXIT STATUS
+.Nm
+exits with the top value left on the stack,
+or 0 if the stack is left empty.
+.
+.Sh STANDARDS
+.Rs
+.%A Chris Pressey
+.%Q Cat's Eye Technologies
+.%T Befunge-93
+.%D September, 1993
+.%U https://github.com/catseye/Befunge-93/blob/master/doc/Befunge-93.markdown
+.Re
diff --git a/bin/man1/bibsort.1 b/bin/man1/bibsort.1
new file mode 100644
index 00000000..07ed91ef
--- /dev/null
+++ b/bin/man1/bibsort.1
@@ -0,0 +1,40 @@
+.Dd February 16, 2021
+.Dt BIBSORT 1
+.Os
+.
+.Sh NAME
+.Nm bibsort
+.Nd reformat bibliography
+.
+.Sh SYNOPSIS
+.Nm
+.Op Ar file
+.
+.Sh DESCRIPTION
+.Nm
+reformats on standard output
+the
+.Em STANDARDS
+section of the
+.Xr mdoc 7
+manual page
+.Ar file
+or standard input.
+Bibliographic references
+are sorted by author last names,
+and formatted in an item list
+with macro lines appearing
+in the order they are formatted by
+.Xr mandoc 1 .
+Additionally,
+.Ic \&%N
+macros referencing RFC numbers
+are rewritten to
+.Ic \&%R
+macros
+and missing
+.Ic \&%U
+macros are added for RFCs.
+.
+.Sh EXAMPLES
+.Dl :%!bibsort
diff --git a/bin/man1/bit.1 b/bin/man1/bit.1
new file mode 100644
index 00000000..b91a10e1
--- /dev/null
+++ b/bin/man1/bit.1
@@ -0,0 +1,55 @@
+.Dd December 30, 2020
+.Dt BIT 1
+.Os
+.
+.Sh NAME
+.Nm bit
+.Nd a calculator
+.
+.Sh SYNOPSIS
+.Nm
+.
+.Sh DESCRIPTION
+.Nm
+is an integer calculator.
+Its syntax resembles that of C expressions,
+with the following changes:
+.
+.Bl -bullet
+.It
+Underscores are allowed in integer literals.
+.It
+The
+.Sy 0b
+prefix is used for binary literals.
+.It
+The
+.Sy ->
+operator is used for arithmetic shift.
+.It
+The unary
+.Sy &
+operator is equivalent to
+.Sy (1 << x) - 1 .
+.It
+The postfix operators
+.Sy K ,
+.Sy M ,
+.Sy G ,
+.Sy T
+are used as constant multipliers.
+.It
+The postfix operator
+.Sy $
+is of lowest precedence and is equivalent to
+wrapping the preceding expression in parentheses.
+.It
+Single-letter (lower case) variables
+can be assigned.
+The variable
+.Sy _
+stores the previous result.
+.El
+.
+.Sh SEE ALSO
+.Xr operator 7
diff --git a/bin/man1/bri.1 b/bin/man1/bri.1
new file mode 100644
index 00000000..54a02322
--- /dev/null
+++ b/bin/man1/bri.1
@@ -0,0 +1,44 @@
+.Dd September 7, 2018
+.Dt BRI 1
+.Os
+.
+.Sh NAME
+.Nm bri
+.Nd backlight brightness control
+.
+.Sh SYNOPSIS
+.Nm
+.Op Ar brightness
+.Nm
+.Cm +
+.Nm
+.Cm -
+.
+.Sh DESCRIPTION
+.Nm
+controls the backlight brightness on Linux.
+.
+.Pp
+With no argument,
+the current brightness is printed.
+With a numerical
+.Ar brightness
+argument,
+the brightness is set.
+.
+.Pp
+The
+.Cm +
+and
+.Cm -
+arguments
+may be repeated any number of times
+and adjust the brightness
+in increments of 16.
+.
+.Sh FILES
+.Bl -tag
+.It Pa /sys/class/backlight
+Files under the first subdirectory found
+are used to control the backlight brightness.
+.El
diff --git a/bin/man1/c.1 b/bin/man1/c.1
new file mode 100644
index 00000000..97384ebe
--- /dev/null
+++ b/bin/man1/c.1
@@ -0,0 +1,45 @@
+.Dd January  9, 2021
+.Dt C 1
+.Os
+.
+.Sh NAME
+.Nm c
+.Nd run C
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl t
+.Op Fl e Ar expr
+.Op Fl i Ar include
+.Op Ar stmts ...
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility compiles and runs
+C statements wrapped in
+.Fn main
+with common includes.
+If no
+.Ar expr
+or
+.Ar stmts
+are provided,
+statements are read from standard input.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl e Ar expr
+Print the result of the C expression
+.Ar expr
+after executing
+.Ar stmts .
+.It Fl i Ar include
+Add the include file
+.Ar include .
+.It Fl t
+With
+.Fl e ,
+print the type of the expression.
+.El
diff --git a/bin/man1/dtch.1 b/bin/man1/dtch.1
new file mode 100644
index 00000000..e27713e1
--- /dev/null
+++ b/bin/man1/dtch.1
@@ -0,0 +1,67 @@
+.Dd August 12, 2019
+.Dt DTCH 1
+.Os
+.
+.Sh NAME
+.Nm dtch
+.Nd detached sessions
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl s
+.Ar name
+.Op Ar command ...
+.Nm
+.Fl a
+.Ar name
+.
+.Sh DESCRIPTION
+.Nm
+spawns a
+.Ar command
+in a detachable session.
+If no
+.Ar command
+is given,
+the value of
+.Ev SHELL
+is used.
+The
+.Nm
+process
+should be run as a background job
+or with
+.Xr nohup 1 .
+.
+.Pp
+To attach to an existing session,
+pass the
+.Fl a
+flag.
+To detach from the session,
+type
+.Ic ^Q .
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Attach to an existing session.
+.It Fl s
+Sink the output of
+.Ar command
+while detached.
+.El
+.
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa ~/.dtch
+Directory of UNIX-domain sockets
+for each session.
+.El
+.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+dtch foo vim &
+dtch -a foo
+.Ed
diff --git a/bin/man1/ever.1 b/bin/man1/ever.1
new file mode 100644
index 00000000..8cdab99b
--- /dev/null
+++ b/bin/man1/ever.1
@@ -0,0 +1,51 @@
+.Dd February 24, 2021
+.Dt EVER 1
+.Os
+.
+.Sh NAME
+.Nm ever
+.Nd watch files
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl iq
+.Ar
+.Ar command
+.Nm
+.Op Fl i
+.Ar
+.Fl -
+.Ar command
+.Op Ar argument ...
+.
+.Sh DESCRIPTION
+.Nm
+executes the
+.Ar command
+whenever
+.Ar file
+is modified.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl i
+Attach the
+.Ar file
+which was modified
+to the standard input of
+.Ar command .
+.It Fl q
+Suppress exit status output.
+.El
+.
+.Sh EXAMPLES
+.Dl ever ever.c make
+.Dl ever when.y ever.c -- make when ever
+.Dl ever -i ever.1 mandoc
+.
+.Sh CAVEATS
+.Nm
+does not support Linux
+since it uses
+.Xr kqueue 2 .
diff --git a/bin/man1/fbatt.1 b/bin/man1/fbatt.1
new file mode 100644
index 00000000..2d30cba7
--- /dev/null
+++ b/bin/man1/fbatt.1
@@ -0,0 +1,34 @@
+.Dd September 7, 2018
+.Dt FBATT 1
+.Os
+.
+.Sh NAME
+.Nm fbatt
+.Nd framebuffer battery indicator
+.
+.Sh SYNOPSIS
+.Nm
+.
+.Sh DESCRIPTION
+.Nm
+displays a battery charge indicator
+in the top-right corner
+of the Linux framebuffer.
+.
+.Sh ENVIRONMENT
+.Bl -tag
+.It Ev FRAMEBUFFER
+The framebuffer device path.
+.El
+.
+.Sh FILES
+.Bl -tag
+.It Pa /dev/fb0
+The default framebuffer device path.
+.It Pa /sys/class/power_supply
+The first subdirectory containing
+.Pa charge_full
+and
+.Pa charge_now
+is used to read the battery charge.
+.El
diff --git a/bin/man1/fbclock.1 b/bin/man1/fbclock.1
new file mode 100644
index 00000000..3195eb42
--- /dev/null
+++ b/bin/man1/fbclock.1
@@ -0,0 +1,36 @@
+.Dd September 7, 2018
+.Dt FBCLOCK 1
+.Os
+.
+.Sh NAME
+.Nm fbclock
+.Nd framebuffer clock
+.
+.Sh SYNOPSIS
+.Nm
+.
+.Sh DESCRIPTION
+.Nm
+displays a clock
+in the top-right corner
+of the Linux framebuffer.
+.
+.Sh ENVIRONMENT
+.Bl -tag
+.It Ev FONT
+Path to gzipped PSF file.
+.
+.It Ev FRAMEBUFFER
+The framebuffer device path.
+.El
+.
+.Sh FILES
+.Bl -tag
+.It Pa /dev/fb0
+The default framebuffer device path.
+.It Pa /usr/share/kbd/consolefonts/Lat2-Terminus16.psfu.gz
+The default font path.
+.El
+.
+.Sh SEE ALSO
+.Xr setfont 8
diff --git a/bin/man1/glitch.1 b/bin/man1/glitch.1
new file mode 100644
index 00000000..6562c4dc
--- /dev/null
+++ b/bin/man1/glitch.1
@@ -0,0 +1,77 @@
+.Dd September 7, 2018
+.Dt GLITCH 1
+.Os
+.
+.Sh NAME
+.Nm glitch
+.Nd PNG glitcher
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl cfimprxy
+.Op Fl a Ar filters
+.Op Fl d Ar filters
+.Op Fl o Ar file
+.Op Ar
+.
+.Sh DESCRIPTION
+.Nm
+misinterprets PNG files
+according to the options given
+to create natural glitch effects.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl a Ar filters
+Apply a pattern of comma-separated filters.
+Filters are
+.Cm none ,
+.Cm sub ,
+.Cm up ,
+.Cm average ,
+.Cm paeth .
+.
+.It Fl c
+Write to standard output.
+.
+.It Fl d Ar filters
+Declare a pattern of comma-separated filters.
+See
+.Fl a
+for list of filters.
+.
+.It Fl f
+Apply filtering in place of reconstruction.
+.
+.It Fl i
+Invert image data after filtering.
+.
+.It Fl m
+Mirror scanlines after filtering.
+.
+.It Fl o Ar file
+Write to
+.Ar file .
+.
+.It Fl p
+Use a broken Paeth predictor function.
+.
+.It Fl r
+Apply reconstruction in place of filtering.
+.
+.It Fl x
+Zero first pixel of each scanline after filtering.
+.
+.It Fl y
+Zero first scanline after filtering.
+.El
+.
+.Sh EXAMPLES
+.Dl glitch -m -a sub -d sub
+.
+.Sh SEE ALSO
+.Xr pngo 1
+.
+.Sh BUGS
+More wanted.
diff --git a/bin/man1/hilex.1 b/bin/man1/hilex.1
new file mode 100644
index 00000000..80b3155b
--- /dev/null
+++ b/bin/man1/hilex.1
@@ -0,0 +1,218 @@
+.Dd January 20, 2021
+.Dt HILEX 1
+.Os
+.
+.Sh NAME
+.Nm hilex
+.Nd syntax highlighter
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl t
+.Op Fl f Ar format
+.Op Fl l Ar lexer
+.Op Fl n Ar name
+.Op Fl o Ar opts
+.Op Ar file
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility
+syntax highlights
+the contents of
+.Ar file
+or standard input
+and formats it on standard output.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width "-f format"
+.It Fl f Ar format
+Set the output format.
+See
+.Sx Output Formats .
+The default format is
+.Cm ansi .
+.
+.It Fl l Ar lexer
+Set the input lexer.
+See
+.Sx Input Lexers .
+The default input lexer is inferred from
+.Ar name
+or the first line of input.
+.
+.It Fl n Ar name
+Set the name used to infer the input lexer.
+The default is the final component of
+.Ar file .
+.
+.It Fl o Ar opts
+Set output format options.
+.Ar opts
+is a comma-separated list of options.
+Options for each output format are documented in
+.Sx Output Formats .
+.
+.It Fl t
+Default to the
+.Cm text
+input lexer if one cannot be inferred.
+.El
+.
+.Ss Output Formats
+.Bl -tag -width Ds
+.It Cm ansi
+Output ANSI terminal control sequences.
+If standard output is a terminal
+and standard input is not being read,
+output is piped to
+.Ev PAGER
+with
+.Ev LESS=FRX
+if it is not already set.
+.
+.It Cm html
+Output HTML
+.Sy span
+elements
+with the following classes:
+.Pp
+.Bl -hang -width "\&Op" -compact
+.It Sy \&Op
+operators
+.It Sy \&Nu
+numbers
+.It Sy \&Ke
+keywords
+.It Sy \&Id
+identifiers
+.It Sy \&Ma
+macros
+.It Sy \&Co
+comments
+.It Sy \&St
+strings
+.It Sy \&Es
+character escapes
+.It Sy \&Fo
+format strings
+.It Sy \&Su
+variable substitutions
+.El
+.Pp
+The options are as follows:
+.Bl -tag -width "title=..."
+.It Cm document
+Output an HTML document containing a
+.Sy pre
+element.
+.It Cm inline
+Output inline style attributes
+rather than classes.
+.It Cm pre
+Wrap the output in a
+.Sy pre
+element with the class
+.Sy hilex .
+.It Cm style Ns = Ns Ar url
+With
+.Cm document ,
+use the external stylesheet
+.Ar url .
+If unset,
+default styles are included in a
+.Sy style
+element.
+.It Cm tab Ns = Ns Ar n
+With
+.Cm document ,
+.Cm inline
+or
+.Cm pre ,
+set the
+.Sy tab-size
+property to
+.Ar n .
+.It Cm title Ns = Ns Ar ...
+With
+.Cm document ,
+set the
+.Sy title
+element text.
+The default title is the same as
+.Ar name .
+.El
+.
+.It Cm irc
+Output IRC formatting codes.
+The options are as follows:
+.Bl -tag -width "monospace"
+.It Cm monospace
+Use the IRCCloud monospace formatting code.
+.El
+.El
+.
+.Ss Input Lexers
+.Bl -tag -width Ds
+.It Cm c
+The C11 language,
+with minimal support for
+.Xr lex 1 ,
+.Xr yacc 1
+and Objective-C input.
+Inferred for
+.Pa *.[chlmy]
+files.
+.
+.It Cm make
+BSD
+.Xr make 1 .
+Inferred for
+.Pa Makefile ,
+.Pa *.mk
+and
+.Pa *.am
+files.
+.
+.It Cm mdoc
+The
+.Xr mdoc 7
+language.
+Inferred for
+.Pa *.[1-9]
+files
+and files starting with
+.Dq .Dd .
+.
+.It Cm sh
+POSIX
+.Xr sh 1 .
+Since lexical analysis of
+the shell command language
+is effectively impossible,
+this is best-effort only.
+Inferred for
+.Pa *.sh ,
+.Pa .profile ,
+.Pa .shrc
+files
+and files starting with
+.Dq #!/bin/sh .
+.
+.It Cm text
+Plain text.
+Inferred for
+.Pa *.txt
+files.
+.El
+.
+.Sh ENVIRONMENT
+.Bl -tag -width "PAGER"
+.It Ev PAGER
+The command to pipe ANSI output to
+if standard output is a terminal.
+The default is
+.Ev PAGER=less .
+.El
diff --git a/bin/man1/htagml.1 b/bin/man1/htagml.1
new file mode 100644
index 00000000..97e8f3f2
--- /dev/null
+++ b/bin/man1/htagml.1
@@ -0,0 +1,69 @@
+.Dd January 12, 2021
+.Dt HTAGML 1
+.Os
+.
+.Sh NAME
+.Nm htagml
+.Nd format tagged file as HTML
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl ip | x
+.Op Fl f Ar tagsfile
+.Ar file
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility formats a file tagged with
+.Xr ctags 1
+as HTML.
+Tags are output as fragment hyperlinks
+with the class
+.Qq tag .
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl f Ar tagsfile
+Read the tag descriptions from a file called
+.Ar tagsfile .
+The default behavior is
+to read them from a file called
+.Pa tags .
+.It Fl i
+Assume
+.Ar file
+has been pre-formatted
+on standard input,
+such as by a syntax highlighter.
+Only tag hyperlinks are added.
+.It Fl p
+Wrap the output in a
+.Sy pre
+element.
+.It Fl x
+Instead produce an index of tags
+ordered by their occurrence in
+.Ar file .
+The index is formatted as a
+.Sy ul
+element with the class
+.Qq index .
+.El
+.
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa tags
+default input tags file
+.El
+.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+ctags htagml.c && htagml htagml.c
+hilex -f html htagml.c | htagml -i htagml.c
+.Ed
+.
+.Sh SEE ALSO
+.Xr ctags 1 ,
+.Xr hilex 1
diff --git a/bin/man1/modem.1 b/bin/man1/modem.1
new file mode 100644
index 00000000..a4bbc3f1
--- /dev/null
+++ b/bin/man1/modem.1
@@ -0,0 +1,31 @@
+.Dd December  8, 2020
+.Dt MODEM 1
+.Os
+.
+.Sh NAME
+.Nm modem
+.Nd fixed baud rate wrapper
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl r Ar rate
+.Ar command ...
+.
+.Sh DESCRIPTION
+.Nm
+runs the
+.Ar command
+in a new PTY
+with a fixed baud rate.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl r Ar rate
+Set the baud rate.
+The default is 19200.
+.El
+.
+.Sh BUGS
+Window size changes are not propagated
+to the child PTY.
diff --git a/bin/man1/mtags.1 b/bin/man1/mtags.1
new file mode 100644
index 00000000..57856ba0
--- /dev/null
+++ b/bin/man1/mtags.1
@@ -0,0 +1,76 @@
+.Dd January 20, 2021
+.Dt MTAGS 1
+.Os
+.
+.Sh NAME
+.Nm mtags
+.Nd miscellaneous tags
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl a
+.Op Fl f Ar tagsfile
+.Ar
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility
+makes a
+.Pa tags
+file for
+.Xr ex 1
+from the specified
+.Xr make 1 ,
+.Xr mdoc 7
+.Xr sh 1
+sources.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Append to
+.Pa tags
+file.
+.It Fl f Ar tagsfile
+Place the tag descriptions
+in a file called
+.Ar tagsfile .
+The default behaviour is
+to place them in a file called
+.Pa tags .
+.El
+.
+.Pp
+Files whose names are
+.Pa Makefile
+or end in
+.Pa .mk
+are assumed to be
+.Xr make 1
+files.
+Files whose names end in
+.Pa .[1-9]
+are assumed to be
+.Xr mdoc 7
+files.
+Files whose names are
+.Pa .profile ,
+.Pa .shrc
+or end in
+.Pa .sh
+are assumed to be
+.Xr sh 1
+files.
+.
+.Sh FILES
+.Bl -tag -width Ds
+.It Pa tags
+default output tags file
+.El
+.
+.Sh SEE ALSO
+.Xr ctags 1 ,
+.Xr ex 1 ,
+.Xr vi 1
diff --git a/bin/man1/nudge.1 b/bin/man1/nudge.1
new file mode 100644
index 00000000..3ca4294a
--- /dev/null
+++ b/bin/man1/nudge.1
@@ -0,0 +1,44 @@
+.Dd September  4, 2020
+.Dt NUDGE 1
+.Os
+.
+.Sh NAME
+.Nm nudge
+.Nd terminal vibrator
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl f Ar file
+.Op Fl n Ar count
+.Op Fl s Ar shake
+.Op Fl t Ar delay
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility
+nudges the terminal.
+An
+.Xr xterm 1
+compatible terminal is required.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl f Ar file
+Open the terminal named by
+.Ar file .
+The default is
+.Pa /dev/tty .
+.It Fl n Ar count
+Set the number of times
+to nudge the terminal.
+The default is 2.
+.It Fl s Ar shake
+Set the shake intensity in pixels.
+The default is 10.
+.It Fl t Ar delay
+Set the interval between shakes
+in milliseconds.
+The default is 20.
+.El
diff --git a/bin/man1/order.1 b/bin/man1/order.1
new file mode 100644
index 00000000..89fcbda5
--- /dev/null
+++ b/bin/man1/order.1
@@ -0,0 +1,38 @@
+.Dd July 18, 2020
+.Dt ORDER 1
+.Os
+.
+.Sh NAME
+.Nm order
+.Nd operator precedence
+.
+.Sh SYNOPSIS
+.Nm
+.Op Ar expr ...
+.
+.Sh DESCRIPTION
+.Nm
+parses C expressions
+and prints them with parentheses
+according to the precedence rules in
+.Xr operator 7 .
+If no
+.Ar expr
+are given,
+an expression is read
+from standard input.
+.
+.Sh EXAMPLES
+.Bd -literal
+$ order 'a & b << 1'
+(a & (b << 1))
+.Ed
+.
+.Sh SEE ALSO
+.Xr operator 7
+.
+.Sh CAVEATS
+.Nm
+does not support the
+.Sy (type)
+operator.
diff --git a/bin/man1/pbd.1 b/bin/man1/pbd.1
new file mode 100644
index 00000000..f0665891
--- /dev/null
+++ b/bin/man1/pbd.1
@@ -0,0 +1,66 @@
+.Dd February  9, 2021
+.Dt PBD 1
+.Os
+.
+.Sh NAME
+.Nm pbd
+.Nd macOS pasteboard daemon
+.
+.Sh SYNOPSIS
+.Nm Op Fl s | c | p | o Ar url
+.
+.Sh DESCRIPTION
+.Nm
+is a daemon which pipes into macOS
+.Xr pbcopy 1 ,
+from
+.Xr pbpaste 1
+and invokes
+.Xr open 1
+in response to messages
+sent over TCP port 7062.
+.
+.Pp
+The socket can be forwarded through
+.Xr ssh 1
+and the flags can be used remotely
+to access the local pasteboard
+and open URLs.
+.
+.Pp
+Forwarding can be configured with:
+.Pp
+.Dl RemoteForward 7062 127.0.0.1:7062
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl c
+Behave as
+.Xr pbcopy 1 .
+.It Fl o Ar url
+Behave as
+.Xr open 1 .
+.It Fl p
+Behave as
+.Xr pbpaste 1 .
+.It Fl s
+Run the server.
+This is the default.
+.El
+.Pp
+ACAB.
+.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+pbd &
+ssh -R 7062:127.0.0.1:7062 tux.local
+pbd -p
+.Ed
+.
+.Sh SEE ALSO
+.Xr open 1 ,
+.Xr pbcopy 1 ,
+.Xr pbpaste 1 ,
+.Xr ssh 1 ,
+.Xr ssh_config 5
diff --git a/bin/man1/pngo.1 b/bin/man1/pngo.1
new file mode 100644
index 00000000..cec13160
--- /dev/null
+++ b/bin/man1/pngo.1
@@ -0,0 +1,56 @@
+.Dd September 17, 2018
+.Dt PNGO 1
+.Os
+.
+.Sh NAME
+.Nm pngo
+.Nd PNG optimizer
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl cv
+.Op Fl o Ar file
+.Op Ar
+.
+.Sh DESCRIPTION
+.Nm
+optimizes PNG files for size.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl c
+Write to standard output.
+.It Fl o Ar file
+Write to
+.Ar file .
+.It Fl v
+Output PNG header information.
+.El
+.
+.Pp
+.Nm
+performs the following optimizations:
+.Bl -bullet
+.It
+Discard ancillary chunks.
+.It
+Discard unnecessary alpha channel.
+.It
+Convert unnecessary truecolor to grayscale.
+.It
+Palletize color and alpha if possible.
+.It
+Reduce bit depth if possible.
+.It
+Apply a simple filter heuristic.
+.It
+Apply zlib's best compresion.
+.El
+.
+.Sh SEE ALSO
+.Xr glitch 1
+.
+.Sh CAVEATS
+.Nm
+does not support interlaced PNGs.
diff --git a/bin/man1/psf2png.1 b/bin/man1/psf2png.1
new file mode 100644
index 00000000..db74c6e2
--- /dev/null
+++ b/bin/man1/psf2png.1
@@ -0,0 +1,53 @@
+.Dd September 28, 2018
+.Dt PSF2PNG 1
+.Os
+.
+.Sh NAME
+.Nm psf2png
+.Nd PSF2 to PNG renderer
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl b Ar bg
+.Op Fl c Ar cols
+.Op Fl f Ar fg
+.Op Fl s Ar str
+.Op Ar file
+.
+.Sh DESCRIPTION
+.Nm
+renders the PSF2 font
+.Ar file
+or standard input
+to PNG
+on standard output.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl b Ar bg
+Use
+.Ar bg
+(hexadecimal RGB)
+as background color.
+The default background color is black.
+.It Fl c Ar cols
+Arrange glyphs in
+.Ar cols
+columns.
+The default number of columns is 32.
+.It Fl f Ar fg
+Use
+.Ar fg
+(hexadecimal RGB)
+as foreground color.
+The default foreground color is white.
+.It Fl s Ar str
+Render glyphs for string
+.Ar str
+rather than all glyphs.
+.El
+.
+.Sh SEE ALSO
+.Xr pngo 1 ,
+.Xr psfed 1
diff --git a/bin/man1/psfed.1 b/bin/man1/psfed.1
new file mode 100644
index 00000000..3fbc4710
--- /dev/null
+++ b/bin/man1/psfed.1
@@ -0,0 +1,166 @@
+.Dd January 14, 2019
+.Dt PSFED 1
+.Os
+.
+.Sh NAME
+.Nm psfed
+.Nd PSF2 font editor
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl H Ar height
+.Op Fl g Ar glyphs
+.Op Fl h Ar height
+.Op Fl w Ar width
+.Ar file
+.
+.Sh DESCRIPTION
+.Nm
+is a PSF2 font editor
+for the Linux framebuffer.
+.
+.Pp
+The arguments are as follows:
+.
+.Bl -tag -width Ds
+.It Fl H Ar height
+Modify the height of an existing font.
+Only increasing the height is allowed.
+.
+.It Fl g Ar glyphs
+Set the number of glyphs in a new font.
+The default number of glyphs is 256.
+.
+.It Fl h Ar height
+Set the height of a new font.
+The default height is 16.
+.
+.It Fl w Ar width
+Set the width of a new font.
+The default width is 8.
+.El
+.
+.Ss Normal Mode
+In normal mode,
+each glyph is displayed in a grid.
+.
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic q
+Quit.
+.Nm
+will ask for confirmation
+if the font has been modified
+since the last write.
+.
+.It Ic w
+Write font to
+.Ar file .
+.
+.It Ic - Ic +
+Adjust display scale.
+.
+.It Ic h Ic l
+Select previous/next glyph.
+.
+.It Ic k Ic j
+Select glyph in previous/next row.
+.
+.It Ic f
+Select glyph of next input character.
+.
+.It Ic '
+Return to previously selected glyph.
+.
+.It Ic y
+Copy selected glyph.
+.
+.It Ic e
+Edit selected glyph in
+.Sx Edit Mode .
+.
+.It Ic i
+Enter
+.Sx Preview Mode .
+.El
+.
+.Ss Edit Mode
+In edit mode,
+the selected glyph is displayed for editing
+surrounded by a checked border.
+The glyph is also displayed unscaled
+in the bottom-right corner.
+.
+.Pp
+.Bl -tag -width Ds -compact
+.It Ic ESC
+Return to
+.Sx Normal Mode .
+.
+.It Ic - Ic +
+Adjust display scale.
+.
+.It Ic g Ic G
+Toggle guide on selected column/row.
+.
+.It Ic h Ic l
+Select previous/next bit in row.
+.
+.It Ic k Ic j
+Select previous/next bit in column.
+.
+.It Ic SPACE
+Flip selected bit.
+.
+.It Ic r
+Invert glyph.
+.
+.It Ic H Ic L
+Move glyph left/right.
+.
+.It Ic K Ic J
+Move glyph up/down.
+.
+.It Ic p
+Paste the copied glyph.
+.
+.It Ic u
+Revert glyph to initial state.
+.El
+.
+.Ss Preview Mode
+In preview mode,
+arbitrary text may be entered
+for preview.
+Press
+.Ic ESC
+to return to
+.Sx Normal Mode .
+.
+.Sh ENVIRONMENT
+.Bl -tag -width FRAMEBUFFER
+.It Ev FRAMEBUFFER
+The framebuffer device path.
+The default path is
+.Pa /dev/fb0 .
+.El
+.
+.Sh SEE ALSO
+.Xr psfaddtable 1 ,
+.Xr psfgettable 1 ,
+.Xr psfstriptable 1 ,
+.Xr setfont 8
+.
+.Sh CAVEATS
+.Nm
+does not support Unicode tables.
+Use
+.Xr psfaddtable 1
+to add Unicode tables
+to fonts created by
+.Nm .
+.
+.Sh BUGS
+.Nm
+makes no attempt to convert header fields
+to and from little-endian format.
diff --git a/bin/man1/ptee.1 b/bin/man1/ptee.1
new file mode 100644
index 00000000..04f9cdac
--- /dev/null
+++ b/bin/man1/ptee.1
@@ -0,0 +1,40 @@
+.Dd July 17, 2019
+.Dt PTEE 1
+.Os
+.
+.Sh NAME
+.Nm ptee
+.Nd tee for PTYs
+.
+.Sh SYNOPSIS
+.Nm
+.Ar command ...
+.Cm >
+.Ar file
+.
+.Sh DESCRIPTION
+.Nm
+runs
+.Ar command
+in a new PTY
+which is mirrored to
+the current PTY
+and standard output.
+Standard output must be redirected
+to a file or pipe.
+.
+.Pp
+Type
+.Ic ^S
+to toggle writing to standard output.
+Type
+.Ic ^Q
+to write the media copy sequence for
+.Xr shotty 1 .
+.
+.Sh SEE ALSO
+.Xr tee 1
+.
+.Sh BUGS
+Window size changes are not propagated
+to the child PTY.
diff --git a/bin/man1/relay.1 b/bin/man1/relay.1
new file mode 100644
index 00000000..402c4726
--- /dev/null
+++ b/bin/man1/relay.1
@@ -0,0 +1,48 @@
+.Dd April 28, 2019
+.Dt RELAY 1
+.Os
+.
+.Sh NAME
+.Nm relay
+.Nd IRC relay bot
+.
+.Sh SYNOPSIS
+.Nm
+.Ar host
+.Ar port
+.Ar nick
+.Ar chan
+.
+.Sh DESCRIPTION
+.Nm
+is one half of an IRC relay pair.
+It connects to
+.Ar host Ns : Ns Ar port
+over TLS
+as
+.Ar nick
+and joins
+.Ar chan .
+.
+.Pp
+.Nm
+outputs messages from
+.Ar chan
+to standard output
+and sends messages to
+.Ar chan
+from standard input.
+Two
+.Nm
+processes can be connected with
+.Xr mkfifo 1 .
+.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+mkfifo a b
+relay a.example.com 6697 relay '#example' <>a >b
+relay b.example.com 6697 relay '#example' <>b >a
+.Ed
+.
+.Sh SEE ALSO
+.Xr mkfifo 1
diff --git a/bin/man1/scheme.1 b/bin/man1/scheme.1
new file mode 100644
index 00000000..9f72d945
--- /dev/null
+++ b/bin/man1/scheme.1
@@ -0,0 +1,59 @@
+.Dd February  6, 2021
+.Dt SCHEME 1
+.Os
+.
+.Sh NAME
+.Nm scheme
+.Nd color scheme
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl Xacghilmstx
+.Op Fl p Ar n
+.
+.Sh DESCRIPTION
+.Nm
+generates a color scheme
+and outputs it in a number of formats.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl X
+Output Xresources for
+.Xr xterm 1 .
+.It Fl a
+Generate the 16 ANSI colors.
+This is the default.
+.It Fl c
+Output a C enum.
+.It Fl g
+Output a swatch PNG.
+.It Fl h
+Output floating point HSV.
+.It Fl i
+Swap black and white.
+.It Fl l
+Output Linux console OSC sequences.
+.It Fl m
+Output a
+.Xr mintty 1
+theme.
+Use with
+.Fl t .
+.It Fl p Ar n
+Generate only the color
+.Ar n .
+.It Fl s
+Output CSS
+for classes named
+.Sy fg Ns Ar n
+and
+.Sy bg Ns Ar n .
+.It Fl t
+Generate the 16 ANSI colors as well as
+background, foreground, bold, selection and cursor colors.
+.It Fl x
+Output hexadecimal RGB.
+This is the default.
+.El
diff --git a/bin/man1/shotty.1 b/bin/man1/shotty.1
new file mode 100644
index 00000000..d5eaa780
--- /dev/null
+++ b/bin/man1/shotty.1
@@ -0,0 +1,92 @@
+.Dd November 25, 2019
+.Dt SHOTTY 1
+.Os
+.
+.Sh NAME
+.Nm shotty
+.Nd terminal capture
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl Bdns
+.Op Fl b Ar bg
+.Op Fl f Ar fg
+.Op Fl h Ar rows
+.Op Fl w Ar cols
+.Op Ar file
+.
+.Sh DESCRIPTION
+.Nm
+interprets terminal output from
+.Ar file
+or standard input
+and produces HTML
+.Sy <pre>
+on standard output.
+.
+.Pp
+Terminal output
+can be captured with
+.Xr ptee 1 .
+.Nm
+targets compatibility with
+.Ev TERM Ns = Ns Cm xterm
+and
+.Ev TERM Ns = Ns Cm xterm-256color
+as used by
+.Xr ncurses 3 .
+A snapshot of the terminal
+is output each time
+a media copy sequence occurs,
+or once at the end of the capture.
+.
+.Pp
+HTML output uses the classes
+.Sy bg Ns Va n
+and
+.Sy fg Ns Va n ,
+and inline styles for
+bold, italic and underline.
+CSS for colors can be generated with
+.Xr scheme 1 .
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width "-w cols"
+.It Fl B
+Replace bold with bright colors.
+.
+.It Fl b Ar bg
+Set the default background color.
+The default value is 0 (black).
+.
+.It Fl d
+Output the terminal state
+following each control sequence.
+.
+.It Fl f Ar fg
+Set the default foreground color.
+The default value is 7 (white).
+.
+.It Fl h Ar rows
+Set the terminal height.
+The default value is 24.
+.
+.It Fl n
+Do not show the cursor.
+.
+.It Fl s
+Set the terminal size
+from the current terminal size.
+.
+.It Fl w Ar cols
+Set the terminal width.
+The default value is 80.
+.El
+.
+.Sh EXAMPLES
+.Dl ptee htop | shotty -s > htop.html
+.
+.Sh SEE ALSO
+.Xr ptee 1 ,
+.Xr scheme 1
diff --git a/bin/man1/sup.1 b/bin/man1/sup.1
new file mode 100644
index 00000000..4b266e06
--- /dev/null
+++ b/bin/man1/sup.1
@@ -0,0 +1,48 @@
+.Dd February 21, 2021
+.Dt SUP 1
+.Os
+.
+.Sh NAME
+.Nm sup
+.Nd single-use password
+.
+.Sh SYNOPSIS
+.Nm
+.Ar service
+.Op Ar email
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility
+sets a random single-use password
+for a service using the
+.Dq forgot password
+or
+.Dq password reset
+flow.
+The password is copied to the clipboard
+and the service login page is opened.
+For passwordless services
+with email-based authentication,
+the emailed login link is opened.
+.
+.Pp
+The following services are supported:
+.Cm asciinema ,
+.Cm discogs ,
+.Cm freebsdbugzilla ,
+.Cm liberapay ,
+.Cm lobsters ,
+.Cm tildenews .
+.
+.Pp
+The
+.Nm
+utility requires
+.Xr curl 1 ,
+.Xr git-fetch-email 1 ,
+.Xr openssl 1 ,
+.Xr pbcopy 1
+and
+.Xr open 1 .
diff --git a/bin/man1/title.1 b/bin/man1/title.1
new file mode 100644
index 00000000..43ecc5e2
--- /dev/null
+++ b/bin/man1/title.1
@@ -0,0 +1,51 @@
+.Dd September 10, 2019
+.Dt TITLE 1
+.Os
+.
+.Sh NAME
+.Nm title
+.Nd page titles
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Op Fl x Ar pattern
+.Op Ar url
+.
+.Sh DESCRIPTION
+.Nm
+fetches HTML page titles
+over HTTP and HTTPS.
+.Nm
+scans standard input for URLs
+and writes their titles to standard output.
+If a
+.Ar url
+argument is given,
+.Nm
+exits after fetching its title.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl x Ar pattern
+Exclude URLs matching
+.Ar pattern ,
+which is a modern regular expression.
+See
+.Xr re_format 7 .
+.It Fl v
+Enable
+.Xr libcurl 3
+verbose output.
+.El
+.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+mkfifo snarf titles
+relay irc.example.org 6697 snarf '#example' <>titles >snarf
+title <snarf >titles
+.Ed
+.
+.Sh SEE ALSO
+.Xr relay 1
diff --git a/bin/man1/typer.1 b/bin/man1/typer.1
new file mode 100644
index 00000000..dd1108d1
--- /dev/null
+++ b/bin/man1/typer.1
@@ -0,0 +1,74 @@
+.Dd April 28, 2021
+.Dt TYPER 1
+.Os
+.
+.Sh NAME
+.Nm typer
+.Nd type all day
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl CPRv
+.Op Fl c Ar cert
+.Op Fl n Ar nick
+.Op Fl p Ar port
+.Op Fl u Ar user
+.Ar host
+.Ar chan
+.
+.Sh DESCRIPTION
+.Nm
+is an IRC bot
+that types all day long.
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl C
+Copy
+.Nm .
+Type whenever anyone else is typing.
+.It Fl P
+Request the
+.Sy causal.agency/passive
+vendor-specific capability.
+.It Fl R
+Reverse
+.Nm .
+Send other users' typing indicators
+as regular messages for all to see.
+.It Fl c Ar cert
+Use the TLS client certificate
+and private key loaded from
+.Ar cert .
+.It Fl n Ar nick
+Set the nickname.
+The default is
+.Nm .
+.It Fl p Ar port
+Connect to
+.Ar port .
+The default is 6697.
+.It Fl u Ar user
+Set the username.
+The default is
+.Nm .
+.It Fl v
+Log IRC protocol to standard error.
+.It Ar host
+Connect to
+.Ar host .
+.It Ar chan
+Type in the channel
+.Ar chan .
+.El
+.
+.Sh STANDARDS
+.Bl -item
+.It
+.Rs
+.%A MuffinMedic
+.%A James Wheare
+.%T IRCv3 typing client tag
+.%I IRCv3 Working Group
+.%U https://ircv3.net/specs/client-tags/typing
+.Re
+.El
diff --git a/bin/man1/up.1 b/bin/man1/up.1
new file mode 100644
index 00000000..189020de
--- /dev/null
+++ b/bin/man1/up.1
@@ -0,0 +1,80 @@
+.Dd February  7, 2021
+.Dt UP 1
+.Os
+.
+.Sh NAME
+.Nm up
+.Nd upload file
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl h
+.Op Ar file
+.
+.Nm
+.Fl c | t
+.Ar command ...
+.
+.Nm
+.Fl s
+.
+.Sh DESCRIPTION
+.Nm
+uploads a file
+to temp.causal.agency with
+.Xr scp 1 .
+If no
+.Ar file
+is provided,
+standard input is read
+and uploaded as text.
+.
+.Pp
+The destination file name
+is chosen using
+.Xr date 1
+and
+.Xr openssl 1
+.Cm rand .
+The URL of the uploaded file is printed
+and copied to the pasteboard with
+.Xr pbcopy 1
+if available.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl c
+Run a command
+to produce a text file for upload.
+.It Fl h
+Use
+.Xr hilex 1
+to produce an HTML file for upload.
+.It Fl s
+Use
+.Xr screencapture 1
+or
+.Xr scrot 1
+to produce a PNG file for upload.
+The file is optimized by
+.Xr pngo 1
+if available.
+.It Fl t
+Run a command with
+.Xr ptee 1
+and
+.Xr shotty 1
+to produce an HTML file for upload.
+.El
+.
+.Pp
+Any arguments after
+.Ql \-\-
+are passed to
+.Xr hilex 1
+and
+.Xr screencapture 1
+or
+.Xr scrot 1 ,
+respectively.
diff --git a/bin/man1/when.1 b/bin/man1/when.1
new file mode 100644
index 00000000..0b473573
--- /dev/null
+++ b/bin/man1/when.1
@@ -0,0 +1,76 @@
+.Dd July 24, 2019
+.Dt WHEN 1
+.Os
+.
+.Sh NAME
+.Nm when
+.Nd date calculator
+.
+.Sh SYNOPSIS
+.Nm
+.Op Ar expr
+.
+.Sh DESCRIPTION
+.Nm
+is a date calculator.
+If no
+.Ar expr
+is given,
+expressions are read
+from standard input.
+.
+.Pp
+The grammar is as follows:
+.Bl -tag -width Ds
+.It Sy \&.
+Today's date.
+.
+.It Ar month Ar date Op Ar year
+A full date,
+or a date in the current year.
+.Ar month
+must be at least three letters.
+.
+.It Ar day
+A day of the week
+in the current week.
+.Ar day
+must be at least three letters.
+.
+.It Sy < Ar date
+The date one week before.
+.
+.It Sy > Ar date
+The date one week after.
+.
+.It Ar date Sy + Ar interval
+The date after some interval.
+.
+.It Ar date Sy - Ar interval
+The date before some interval.
+.
+.It Ar date Sy - Ar date
+The interval between two dates.
+.
+.It Ar num Sy d
+A number of days.
+.
+.It Ar num Sy w
+A number of weeks.
+.
+.It Ar num Sy m
+A number of months.
+.
+.It Ar num Sy y
+A number of years.
+.El
+.
+.Sh EXAMPLES
+.Bl -tag -width "Dec 25 - ."
+.It Ic Dec 25 - \&.
+How long until Christmas.
+.It Ic >Fri
+The date next Friday.
+.It Ic \&. + 2w
+Your last day at work.
+.El
diff --git a/bin/man1/xx.1 b/bin/man1/xx.1
new file mode 100644
index 00000000..d38789a7
--- /dev/null
+++ b/bin/man1/xx.1
@@ -0,0 +1,68 @@
+.Dd September 7, 2018
+.Dt XX 1
+.Os
+.
+.Sh NAME
+.Nm xx
+.Nd hexdump
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl arsz
+.Op Fl c Ar cols
+.Op Fl g Ar group
+.Op Fl p Ar count
+.Op Ar file
+.
+.Sh DESCRIPTION
+.Nm
+dumps the contents of a
+.Ar file
+or standard input
+in hexadecimal format.
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl a
+Toggle ASCII output.
+.
+.It Fl c Ar cols
+Output
+.Ar cols
+bytes per line.
+The default
+.Ar cols
+is 16.
+.
+.It Fl g Ar group
+Output extra space after every
+.Ar group
+bytes.
+The default
+.Ar group
+is 8.
+.
+.It Fl p Ar count
+Output a blank line after every
+.Ar count
+bytes.
+.Ar count
+must be a multiple of
+.Ar cols .
+.
+.It Fl r
+Reverse hexdump.
+Read hexadecimal input
+and write byte output.
+.
+.It Fl s
+Toggle offset output.
+.
+.It Fl z
+Skip output of lines containing only zeros.
+.El
+.
+.Sh SEE ALSO
+.Xr hexdump 1 ,
+.Xr xxd 1
diff --git a/bin/man3/png.3 b/bin/man3/png.3
new file mode 100644
index 00000000..accffbd7
--- /dev/null
+++ b/bin/man3/png.3
@@ -0,0 +1,90 @@
+.Dd July 25, 2019
+.Dt PNG 3
+.Os
+.
+.Sh NAME
+.Nm png
+.Nd basic PNG output
+.
+.Sh SYNOPSIS
+.In png.h
+.
+.Ft void
+.Fo pngHead
+.Fa "FILE *file"
+.Fa "uint32_t width"
+.Fa "uint32_t height"
+.Fa "uint8_t depth"
+.Fa "uint8_t color"
+.Fc
+.
+.Ft void
+.Fn pngPalette "FILE *file" "const uint8_t *pal" "uint32_t len"
+.
+.Ft void
+.Fn pngData "FILE *file" "const uint8_t *data" "uint32_t len"
+.
+.Ft void
+.Fn pngTail "FILE *file"
+.
+.Sh DESCRIPTION
+The
+.Fn pngHead
+function
+writes the
+.Sy IHDR
+chunk to
+.Fa file .
+The
+.Fa color
+parameter can be one of
+.Dv PNGGrayscale ,
+.Dv PNGTruecolor
+optionally
+.Em or Ns 'ed
+with
+.Dv PNGAlpha ,
+or
+.Dv PNGIndexed .
+.
+.Pp
+The
+.Fn pngPalette
+function
+writes the
+.Sy PLTE
+chunk to
+.Fa file .
+.
+.Pp
+The
+.Fn pngData
+function
+writes the
+.Sy IDAT
+chunk to
+.Fa file
+without compression.
+The constants
+.Dv PNGNone ,
+.Dv PNGSub ,
+.Dv PNGUp ,
+.Dv PNGAverage ,
+.Dv PNGPaeth
+are defined
+for use in PNG data.
+.
+.Pp
+The
+.Fn pngTail
+function
+writes the
+.Sy IEND
+chunk to
+.Fa file .
+.
+.Sh ERRORS
+Any errors from writing to
+.Fa file
+are handled by calling
+.Xr err 3 .
diff --git a/bin/man6/freecell.6 b/bin/man6/freecell.6
new file mode 100644
index 00000000..0e485a16
--- /dev/null
+++ b/bin/man6/freecell.6
@@ -0,0 +1,50 @@
+.Dd April 17, 2021
+.Dt FREECELL 6
+.Os
+.
+.Sh NAME
+.Nm freecell
+.Nd patience game
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl d Ar delay
+.Op Fl n Ar game
+.
+.Sh DESCRIPTION
+.Nm
+is a terminal FreeCell patience game.
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl d Ar delay
+Set the delay in milliseconds
+between queued moves.
+The default is 50.
+.It Fl n Ar game
+Select the game number to play.
+.El
+.
+.Pp
+Moves are performed
+by typing a sequence of two keys.
+To automatically move a card
+to a free cell,
+type the same key twice.
+The keys are as follows:
+.Bl -tag -width Ds
+.It Ic Escape
+Cancel a pending move.
+.It Ic u , Backspace
+Undo the previous move.
+.It Ic 1 , 2 , 3 , 4
+Select the cells.
+.It Ic q , w , e , r , a , s , d , f
+Select the tableau cascades.
+.It Ic _ , Space
+Manually move
+the selected card
+to the foundations.
+.It Ic Shift
+Move a single card
+to an empty tableau cascade.
+.El
diff --git a/bin/mdoc.l b/bin/mdoc.l
new file mode 100644
index 00000000..2680b722
--- /dev/null
+++ b/bin/mdoc.l
@@ -0,0 +1,65 @@
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%option prefix="mdoc"
+%option noyywrap
+
+%{
+#include "hilex.h"
+%}
+
+%s MacroLine
+
+%%
+
+[[:blank:]]+ { return Normal; }
+
+^"." {
+	BEGIN(MacroLine);
+	return Keyword;
+}
+
+^".\\\"".* { return Comment; }
+
+<MacroLine>{
+	"\n" {
+		BEGIN(0);
+		return Normal;
+	}
+
+	%[ABCDIJNOPQRTUV]|A[cdnopqrt]|B[cdfkloqtx]|Br[coq]|Bsx|C[dm]|D[1bcdloqtvx] |
+	E[cdfklmnorsvx]|F[acdlnortx]|Hf|I[cnt]|L[bikp]|M[st]|N[dmosx]|O[copstx] |
+	P[acfopq]|Q[cloq]|R[esv]|S[chmoqstxy]|T[an]|U[dx]|V[at]|X[cor] {
+		return Keyword;
+	}
+
+	"\""([^""]|"\\\"")*"\"" { return String; }
+}
+
+"\\"(.|"("..|"["[^]]*"]") { return String; }
+
+[^.\\""[:space:]]+ { return Normal; }
+
+.|\n { return Normal; }
+
+%{
+	(void)yyunput;
+	(void)input;
+%}
+
+%%
+
+const struct Lexer LexMdoc = { yylex, &yyin, &yytext };
diff --git a/bin/modem.c b/bin/modem.c
new file mode 100644
index 00000000..4392e071
--- /dev/null
+++ b/bin/modem.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
+
+#if defined __FreeBSD__
+#include <libutil.h>
+#elif defined __linux__
+#include <pty.h>
+#else
+#include <util.h>
+#endif
+
+typedef unsigned uint;
+typedef unsigned char byte;
+
+static struct termios saveTerm;
+static void restoreTerm(void) {
+	tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm);
+}
+
+int main(int argc, char *argv[]) {
+	int error;
+
+	uint baudRate = 19200;
+	for (int opt; 0 < (opt = getopt(argc, argv, "r:"));) {
+		switch (opt) {
+			break; case 'r': baudRate = strtoul(optarg, NULL, 10);
+			break; default:  return EX_USAGE;
+		}
+	}
+	if (argc - optind < 1) return EX_USAGE;
+
+	error = tcgetattr(STDIN_FILENO, &saveTerm);
+	if (error) err(EX_IOERR, "tcgetattr");
+	atexit(restoreTerm);
+
+	struct termios raw = saveTerm;
+	cfmakeraw(&raw);
+	error = tcsetattr(STDIN_FILENO, TCSADRAIN, &raw);
+	if (error) err(EX_IOERR, "tcsetattr");
+
+	struct winsize window;
+	error = ioctl(STDIN_FILENO, TIOCGWINSZ, &window);
+	if (error) err(EX_IOERR, "TIOCGWINSZ");
+
+	int pty;
+	pid_t pid = forkpty(&pty, NULL, NULL, &window);
+	if (pid < 0) err(EX_OSERR, "forkpty");
+
+	if (!pid) {
+		execvp(argv[optind], &argv[optind]);
+		err(EX_NOINPUT, "%s", argv[optind]);
+	}
+
+	byte c;
+	struct pollfd fds[2] = {
+		{ .events = POLLIN, .fd = STDIN_FILENO },
+		{ .events = POLLIN, .fd = pty },
+	};
+	while (usleep(8 * 1000000 / baudRate), 0 < poll(fds, 2, -1)) {
+		if (fds[0].revents) {
+			ssize_t size = read(STDIN_FILENO, &c, 1);
+			if (size < 0) err(EX_IOERR, "read(%d)", STDIN_FILENO);
+			size = write(pty, &c, 1);
+			if (size < 0) err(EX_IOERR, "write(%d)", pty);
+		}
+
+		if (fds[1].revents) {
+			ssize_t size = read(pty, &c, 1);
+			if (size < 0) err(EX_IOERR, "read(%d)", pty);
+			if (!size) break;
+			size = write(STDOUT_FILENO, &c, 1);
+			if (size < 0) err(EX_IOERR, "write(%d)", STDOUT_FILENO);
+		}
+	}
+
+	int status;
+	pid_t dead = waitpid(pid, &status, 0);
+	if (dead < 0) err(EX_OSERR, "waitpid");
+	return WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE;
+}
diff --git a/bin/mtags.c b/bin/mtags.c
new file mode 100644
index 00000000..282d9f03
--- /dev/null
+++ b/bin/mtags.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static void escape(FILE *file, const char *str, size_t len) {
+	for (size_t i = 0; i < len; ++i) {
+		if (str[i] == '\\' || str[i] == '/') {
+			putc('\\', file);
+		}
+		putc(str[i], file);
+	}
+}
+
+int main(int argc, char *argv[]) {
+	bool append = false;
+	const char *path = "tags";
+	for (int opt; 0 < (opt = getopt(argc, argv, "af:"));) {
+		switch (opt) {
+			break; case 'a': append = true;
+			break; case 'f': path = optarg;
+			break; default:  return EX_USAGE;
+		}
+	}
+
+	FILE *tags = fopen(path, (append ? "a" : "w"));
+	if (!tags) err(EX_CANTCREAT, "%s", path);
+
+	regex_t makeFile, makeLine;
+	regex_t mdocFile, mdocLine;
+	regex_t shFile, shLine;
+	int error = 0
+		|| regcomp(&makeFile, "(^|/)Makefile|[.]mk$", REG_EXTENDED | REG_NOSUB)
+		|| regcomp(
+			&makeLine,
+			"^([.][^:$A-Z][^:$[:space:]]*|[^.:$][^:$[:space:]]*):",
+			REG_EXTENDED
+		)
+		|| regcomp(&mdocFile, "[.][1-9]$", REG_EXTENDED | REG_NOSUB)
+		|| regcomp(&mdocLine, "^[.]S[hs] ([^\t\n]+)", REG_EXTENDED)
+		|| regcomp(
+			&shFile, "(^|/)[.](profile|shrc)|[.]sh$", REG_EXTENDED | REG_NOSUB
+		)
+		|| regcomp(&shLine, "^([_[:alnum:]]+)[[:blank:]]*[(][)]", REG_EXTENDED);
+	assert(!error);
+
+	size_t cap = 0;
+	char *buf = NULL;
+	for (int i = optind; i < argc; ++i) {
+		const regex_t *regex;
+		if (!regexec(&makeFile, argv[i], 0, NULL, 0)) {
+			regex = &makeLine;
+		} else if (!regexec(&mdocFile, argv[i], 0, NULL, 0)) {
+			regex = &mdocLine;
+		} else if (!regexec(&shFile, argv[i], 0, NULL, 0)) {
+			regex = &shLine;
+		} else {
+			warnx("skipping unknown file type %s", argv[i]);
+			continue;
+		}
+
+		FILE *file = fopen(argv[i], "r");
+		if (!file) err(EX_NOINPUT, "%s", argv[i]);
+
+		while (0 < getline(&buf, &cap, file)) {
+			regmatch_t match[2];
+			if (regexec(regex, buf, 2, match, 0)) continue;
+			fprintf(
+				tags, "%.*s\t%s\t/^",
+				(int)(match[1].rm_eo - match[1].rm_so), &buf[match[1].rm_so],
+				argv[i]
+			);
+			escape(tags, buf, match[0].rm_eo);
+			fprintf(tags, "/\n");
+		}
+		fclose(file);
+	}
+}
diff --git a/bin/nudge.c b/bin/nudge.c
new file mode 100644
index 00000000..8ae916eb
--- /dev/null
+++ b/bin/nudge.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
+
+static int shake = 10;
+static int delay = 20000;
+static int count = 2;
+
+static void move(int tty, int x, int y) {
+	dprintf(tty, "\33[3;%d;%dt", x, y);
+	usleep(delay);
+}
+
+int main(int argc, char *argv[]) {
+	const char *path = "/dev/tty";
+	for (int opt; 0 < (opt = getopt(argc, argv, "f:n:s:t:"));) {
+		switch (opt) {
+			break; case 'f': path = optarg;
+			break; case 'n': count = atoi(optarg);
+			break; case 's': shake = atoi(optarg);
+			break; case 't': delay = atoi(optarg) * 1000;
+			break; default:  return EX_USAGE;
+		}
+	}
+
+	int tty = open(path, O_RDWR);
+	if (tty < 0) err(EX_OSFILE, "%s", path);
+
+	struct termios save;
+	int error = tcgetattr(tty, &save);
+	if (error) err(EX_IOERR, "tcgetattr");
+
+	struct termios raw = save;
+	cfmakeraw(&raw);
+	error = tcsetattr(tty, TCSAFLUSH, &raw);
+	if (error) err(EX_IOERR, "tcsetattr");
+
+	char buf[256];
+	dprintf(tty, "\33[13t");
+	ssize_t len = read(tty, buf, sizeof(buf) - 1);
+	buf[(len < 0 ? 0 : len)] = '\0';
+
+	int x, y;
+	int n = sscanf(buf, "\33[3;%d;%dt", &x, &y);
+
+	error = tcsetattr(tty, TCSANOW, &save);
+	if (error) err(EX_IOERR, "tcsetattr");
+	if (n < 2) return EX_CONFIG;
+
+	dprintf(tty, "\33[5t");
+	for (int i = 0; i < count; ++i) {
+		move(tty, x - shake, y);
+		move(tty, x, y + shake);
+		move(tty, x + shake, y);
+		move(tty, x, y - shake);
+		move(tty, x, y);
+	}
+}
diff --git a/bin/order.y b/bin/order.y
new file mode 100644
index 00000000..b3cbf2df
--- /dev/null
+++ b/bin/order.y
@@ -0,0 +1,195 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%{
+
+#include <ctype.h>
+#include <err.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#define YYSTYPE char *
+
+static char *fmt(const char *format, ...) {
+	char *str = NULL;
+	va_list ap;
+	va_start(ap, format);
+	vasprintf(&str, format, ap);
+	va_end(ap);
+	if (!str) err(EX_OSERR, "vasprintf");
+	return str;
+}
+
+static int yylex(void);
+static void yyerror(const char *str);
+
+%}
+
+%token Ident
+
+%left ','
+%right '=' MulAss DivAss ModAss AddAss SubAss ShlAss ShrAss AndAss XorAss OrAss
+%right '?' ':'
+%left Or
+%left And
+%left '|'
+%left '^'
+%left '&'
+%left Eq Ne
+%left '<' Le '>' Ge
+%left Shl Shr
+%left '+' '-'
+%left '*' '/' '%'
+%right '!' '~' Inc Dec Sizeof
+%left '(' ')' '[' ']' Arr '.'
+
+%%
+
+start:
+	expr { printf("%s\n", $1); }
+	;
+
+expr:
+	Ident
+	| '(' expr ')' { $$ = $2; }
+	| expr '[' expr ']' { $$ = fmt("(%s[%s])", $1, $3); }
+	| expr Arr Ident { $$ = fmt("(%s->%s)", $1, $3); }
+	| expr '.' Ident { $$ = fmt("(%s.%s)", $1, $3); }
+	| '!' expr { $$ = fmt("(!%s)", $2); }
+	| '~' expr { $$ = fmt("(~%s)", $2); }
+	| Inc expr { $$ = fmt("(++%s)", $2); }
+	| Dec expr { $$ = fmt("(--%s)", $2); }
+	| expr Inc { $$ = fmt("(%s++)", $1); }
+	| expr Dec { $$ = fmt("(%s--)", $1); }
+	| '+' expr %prec '!' { $$ = fmt("(+%s)", $2); }
+	| '-' expr %prec '!' { $$ = fmt("(-%s)", $2); }
+	| '*' expr %prec '!' { $$ = fmt("(*%s)", $2); }
+	| '&' expr %prec '!' { $$ = fmt("(&%s)", $2); }
+	| Sizeof expr { $$ = fmt("(sizeof %s)", $2); }
+	| expr '*' expr { $$ = fmt("(%s * %s)", $1, $3); }
+	| expr '/' expr { $$ = fmt("(%s / %s)", $1, $3); }
+	| expr '%' expr { $$ = fmt("(%s %% %s)", $1, $3); }
+	| expr '+' expr { $$ = fmt("(%s + %s)", $1, $3); }
+	| expr '-' expr { $$ = fmt("(%s - %s)", $1, $3); }
+	| expr Shl expr { $$ = fmt("(%s << %s)", $1, $3); }
+	| expr Shr expr { $$ = fmt("(%s >> %s)", $1, $3); }
+	| expr '<' expr { $$ = fmt("(%s < %s)", $1, $3); }
+	| expr Le expr { $$ = fmt("(%s <= %s)", $1, $3); }
+	| expr '>' expr { $$ = fmt("(%s > %s)", $1, $3); }
+	| expr Ge expr { $$ = fmt("(%s >= %s)", $1, $3); }
+	| expr Eq expr { $$ = fmt("(%s == %s)", $1, $3); }
+	| expr Ne expr { $$ = fmt("(%s != %s)", $1, $3); }
+	| expr '&' expr { $$ = fmt("(%s & %s)", $1, $3); }
+	| expr '^' expr { $$ = fmt("(%s ^ %s)", $1, $3); }
+	| expr '|' expr { $$ = fmt("(%s | %s)", $1, $3); }
+	| expr And expr { $$ = fmt("(%s && %s)", $1, $3); }
+	| expr Or expr { $$ = fmt("(%s || %s)", $1, $3); }
+	| expr '?' expr ':' expr { $$ = fmt("(%s ? %s : %s)", $1, $3, $5); }
+	| expr ass expr %prec '=' { $$ = fmt("(%s %s %s)", $1, $2, $3); }
+	| expr ',' expr { $$ = fmt("(%s, %s)", $1, $3); }
+	;
+
+ass:
+	'=' { $$ = "="; }
+	| MulAss { $$ = "*="; }
+	| DivAss { $$ = "/="; }
+	| ModAss { $$ = "%="; }
+	| AddAss { $$ = "+="; }
+	| SubAss { $$ = "-="; }
+	| ShlAss { $$ = "<<="; }
+	| ShrAss { $$ = ">>="; }
+	| AndAss { $$ = "&="; }
+	| XorAss { $$ = "^="; }
+	| OrAss { $$ = "|="; }
+	;
+
+%%
+
+#define T(a, b) ((int)(a) << 8 | (int)(b))
+
+static FILE *in;
+
+static int yylex(void) {
+	char ch;
+	while (isspace(ch = getc(in)));
+
+	if (isalnum(ch)) {
+		char ident[64] = { ch, '\0' };
+		for (size_t i = 1; i < sizeof(ident) - 1; ++i) {
+			ch = getc(in);
+			if (!isalnum(ch) && ch != '_') break;
+			ident[i] = ch;
+		}
+		ungetc(ch, in);
+		if (!strcmp(ident, "sizeof")) return Sizeof;
+		yylval = fmt("%s", ident);
+		return Ident;
+	}
+
+	char ne = getc(in);
+	switch (T(ch, ne)) {
+		case T('-', '>'): return Arr;
+		case T('+', '+'): return Inc;
+		case T('-', '-'): return Dec;
+		case T('<', '='): return Le;
+		case T('>', '='): return Ge;
+		case T('=', '='): return Eq;
+		case T('!', '='): return Ne;
+		case T('&', '&'): return And;
+		case T('|', '|'): return Or;
+		case T('*', '='): return MulAss;
+		case T('/', '='): return DivAss;
+		case T('%', '='): return ModAss;
+		case T('+', '='): return AddAss;
+		case T('-', '='): return SubAss;
+		case T('&', '='): return AndAss;
+		case T('^', '='): return XorAss;
+		case T('|', '='): return OrAss;
+		case T('<', '<'): {
+			if ('=' == (ne = getc(in))) return ShlAss;
+			ungetc(ne, in);
+			return Shl;
+		}
+		case T('>', '>'): {
+			if ('=' == (ne = getc(in))) return ShrAss;
+			ungetc(ne, in);
+			return Shr;
+		}
+		default: {
+			ungetc(ne, in);
+			return ch;
+		}
+	}
+}
+
+static void yyerror(const char *str) {
+	errx(EX_DATAERR, "%s", str);
+}
+
+int main(int argc, char *argv[]) {
+	for (int i = 1; i < argc; ++i) {
+		in = fmemopen(argv[i], strlen(argv[i]), "r");
+		if (!in) err(EX_OSERR, "fmemopen");
+		yyparse();
+		fclose(in);
+	}
+	if (argc > 1) return EX_OK;
+	in = stdin;
+	yyparse();
+}
diff --git a/bin/pbd.c b/bin/pbd.c
new file mode 100644
index 00000000..9f47b63e
--- /dev/null
+++ b/bin/pbd.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2017  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arpa/inet.h>
+#include <err.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+typedef unsigned char byte;
+
+static void spawn(const char *cmd, const char *arg, int dest, int src) {
+	pid_t pid = fork();
+	if (pid < 0) err(EX_OSERR, "fork");
+
+	if (pid) {
+		int status;
+		pid_t dead = waitpid(pid, &status, 0);
+		if (dead < 0) err(EX_OSERR, "waitpid(%d)", pid);
+		if (status) warnx("%s: status %d", cmd, status);
+
+	} else {
+		int fd = dup2(src, dest);
+		if (fd < 0) err(EX_OSERR, "dup2");
+
+		execlp(cmd, cmd, arg, NULL);
+		err(EX_UNAVAILABLE, "%s", cmd);
+	}
+}
+
+static int pbd(void) {
+	int error;
+
+	int server = socket(PF_INET, SOCK_STREAM, 0);
+	if (server < 0) err(EX_OSERR, "socket");
+
+	error = fcntl(server, F_SETFD, FD_CLOEXEC);
+	if (error) err(EX_IOERR, "fcntl");
+
+	struct sockaddr_in addr = {
+		.sin_family = AF_INET,
+		.sin_port = htons(7062),
+		.sin_addr = { .s_addr = htonl(0x7F000001) },
+	};
+	error = bind(server, (struct sockaddr *)&addr, sizeof(addr));
+	if (error) err(EX_UNAVAILABLE, "bind");
+
+	error = listen(server, 0);
+	if (error) err(EX_UNAVAILABLE, "listen");
+
+	for (;;) {
+		int client = accept(server, NULL, NULL);
+		if (client < 0) err(EX_IOERR, "accept");
+
+		error = fcntl(client, F_SETFD, FD_CLOEXEC);
+		if (error) err(EX_IOERR, "fcntl");
+
+		char c = 0;
+		ssize_t size = read(client, &c, 1);
+		if (size < 0) warn("read");
+
+		switch (c) {
+			break; case 'p': spawn("pbpaste", NULL, STDOUT_FILENO, client);
+			break; case 'c': spawn("pbcopy", NULL, STDIN_FILENO, client);
+			break; case 'o': spawn("xargs", "open", STDIN_FILENO, client);
+		}
+
+		close(client);
+	}
+}
+
+static int pbdClient(char c) {
+	int client = socket(PF_INET, SOCK_STREAM, 0);
+	if (client < 0) err(EX_OSERR, "socket");
+
+	struct sockaddr_in addr = {
+		.sin_family = AF_INET,
+		.sin_port = htons(7062),
+		.sin_addr = { .s_addr = htonl(0x7F000001) },
+	};
+	int error = connect(client, (struct sockaddr *)&addr, sizeof(addr));
+	if (error) err(EX_UNAVAILABLE, "connect");
+
+	ssize_t size = write(client, &c, 1);
+	if (size < 0) err(EX_IOERR, "write");
+
+	return client;
+}
+
+static void copy(int out, int in) {
+	byte buf[4096];
+	ssize_t readSize;
+	while (0 < (readSize = read(in, buf, sizeof(buf)))) {
+		ssize_t writeSize = write(out, buf, readSize);
+		if (writeSize < 0) err(EX_IOERR, "write(%d)", out);
+	}
+	if (readSize < 0) err(EX_IOERR, "read(%d)", in);
+}
+
+static int pbcopy(void) {
+	int client = pbdClient('c');
+	copy(client, STDIN_FILENO);
+	return EX_OK;
+}
+
+static int pbpaste(void) {
+	int client = pbdClient('p');
+	copy(STDOUT_FILENO, client);
+	return EX_OK;
+}
+
+static int open1(const char *url) {
+	if (!url) return EX_USAGE;
+	int client = pbdClient('o');
+	ssize_t size = write(client, url, strlen(url));
+	if (size < 0) err(EX_IOERR, "write");
+	return EX_OK;
+}
+
+int main(int argc, char *argv[]) {
+	for (int opt; 0 < (opt = getopt(argc, argv, "co:ps"));) {
+		switch (opt) {
+			case 'c': return pbcopy();
+			case 'o': return open1(optarg);
+			case 'p': return pbpaste();
+			case 's': return pbd();
+			default:  return EX_USAGE;
+		}
+	}
+	return pbd();
+}
diff --git a/bin/png.h b/bin/png.h
new file mode 100644
index 00000000..0df4699b
--- /dev/null
+++ b/bin/png.h
@@ -0,0 +1,108 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+static inline uint32_t pngCRCTable(uint8_t n) {
+	static uint32_t table[256];
+	if (table[1]) return table[n];
+	for (int i = 0; i < 256; ++i) {
+		table[i] = i;
+		for (int j = 0; j < 8; ++j) {
+			table[i] = (table[i] >> 1) ^ (table[i] & 1 ? 0xEDB88320 : 0);
+		}
+	}
+	return table[n];
+}
+
+static uint32_t pngCRC;
+
+static inline void pngWrite(FILE *file, const uint8_t *ptr, uint32_t len) {
+	if (!fwrite(ptr, len, 1, file)) err(EX_IOERR, "pngWrite");
+	for (uint32_t i = 0; i < len; ++i) {
+		pngCRC = pngCRCTable(pngCRC ^ ptr[i]) ^ (pngCRC >> 8);
+	}
+}
+static inline void pngInt32(FILE *file, uint32_t n) {
+	pngWrite(file, (uint8_t []) { n >> 24, n >> 16, n >> 8, n }, 4);
+}
+static inline void pngChunk(FILE *file, char type[static 4], uint32_t len) {
+	pngInt32(file, len);
+	pngCRC = ~0;
+	pngWrite(file, (uint8_t *)type, 4);
+}
+
+enum {
+	PNGGrayscale,
+	PNGTruecolor = 2,
+	PNGIndexed,
+	PNGAlpha,
+};
+
+static inline void pngHead(
+	FILE *file, uint32_t width, uint32_t height, uint8_t depth, uint8_t color
+) {
+	pngWrite(file, (uint8_t *)"\x89PNG\r\n\x1A\n", 8);
+	pngChunk(file, "IHDR", 13);
+	pngInt32(file, width);
+	pngInt32(file, height);
+	pngWrite(file, &depth, 1);
+	pngWrite(file, &color, 1);
+	pngWrite(file, (uint8_t []) { 0, 0, 0 }, 3);
+	pngInt32(file, ~pngCRC);
+}
+
+static inline void pngPalette(FILE *file, const uint8_t *pal, uint32_t len) {
+	pngChunk(file, "PLTE", len);
+	pngWrite(file, pal, len);
+	pngInt32(file, ~pngCRC);
+}
+
+enum {
+	PNGNone,
+	PNGSub,
+	PNGUp,
+	PNGAverage,
+	PNGPaeth,
+};
+
+static inline void pngData(FILE *file, const uint8_t *data, uint32_t len) {
+	uint32_t adler1 = 1, adler2 = 0;
+	for (uint32_t i = 0; i < len; ++i) {
+		adler1 = (adler1 + data[i]) % 65521;
+		adler2 = (adler1 + adler2) % 65521;
+	}
+	uint32_t zlen = 2 + 5 * ((len + 0xFFFE) / 0xFFFF) + len + 4;
+	pngChunk(file, "IDAT", zlen);
+	pngWrite(file, (uint8_t []) { 0x08, 0x1D }, 2);
+	for (; len > 0xFFFF; data += 0xFFFF, len -= 0xFFFF) {
+		pngWrite(file, (uint8_t []) { 0x00, 0xFF, 0xFF, 0x00, 0x00 }, 5);
+		pngWrite(file, data, 0xFFFF);
+	}
+	pngWrite(file, (uint8_t []) { 0x01, len, len >> 8, ~len, ~len >> 8 }, 5);
+	pngWrite(file, data, len);
+	pngInt32(file, adler2 << 16 | adler1);
+	pngInt32(file, ~pngCRC);
+}
+
+static inline void pngTail(FILE *file) {
+	pngChunk(file, "IEND", 0);
+	pngInt32(file, ~pngCRC);
+}
diff --git a/bin/pngo.c b/bin/pngo.c
new file mode 100644
index 00000000..080e0b95
--- /dev/null
+++ b/bin/pngo.c
@@ -0,0 +1,812 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <arpa/inet.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#define PACKED __attribute__((packed))
+#define PAIR(a, b) ((uint16_t)(a) << 8 | (uint16_t)(b))
+
+#define CRC_INIT (crc32(0, Z_NULL, 0))
+
+static bool verbose;
+static const char *path;
+static FILE *file;
+static uint32_t crc;
+
+static void readExpect(void *ptr, size_t size, const char *expect) {
+	fread(ptr, size, 1, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+	if (feof(file)) errx(EX_DATAERR, "%s: missing %s", path, expect);
+	crc = crc32(crc, ptr, size);
+}
+
+static void writeExpect(const void *ptr, size_t size) {
+	fwrite(ptr, size, 1, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+	crc = crc32(crc, ptr, size);
+}
+
+static const uint8_t Signature[8] = "\x89PNG\r\n\x1A\n";
+
+static void readSignature(void) {
+	uint8_t signature[8];
+	readExpect(signature, 8, "signature");
+	if (0 != memcmp(signature, Signature, 8)) {
+		errx(EX_DATAERR, "%s: invalid signature", path);
+	}
+}
+
+static void writeSignature(void) {
+	writeExpect(Signature, sizeof(Signature));
+}
+
+struct PACKED Chunk {
+	uint32_t size;
+	char type[4];
+};
+
+static const char *typeStr(struct Chunk chunk) {
+	static char buf[5];
+	memcpy(buf, chunk.type, 4);
+	return buf;
+}
+
+static struct Chunk readChunk(void) {
+	struct Chunk chunk;
+	readExpect(&chunk, sizeof(chunk), "chunk");
+	chunk.size = ntohl(chunk.size);
+	crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type));
+	return chunk;
+}
+
+static void writeChunk(struct Chunk chunk) {
+	chunk.size = htonl(chunk.size);
+	writeExpect(&chunk, sizeof(chunk));
+	crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type));
+}
+
+static void readCrc(void) {
+	uint32_t expected = crc;
+	uint32_t found;
+	readExpect(&found, sizeof(found), "CRC32");
+	found = ntohl(found);
+	if (found != expected) {
+		errx(
+			EX_DATAERR, "%s: expected CRC32 %08X, found %08X",
+			path, expected, found
+		);
+	}
+}
+
+static void writeCrc(void) {
+	uint32_t net = htonl(crc);
+	writeExpect(&net, sizeof(net));
+}
+
+static void skipChunk(struct Chunk chunk) {
+	if (!(chunk.type[0] & 0x20)) {
+		errx(EX_CONFIG, "%s: unsupported critical chunk %s", path, typeStr(chunk));
+	}
+	uint8_t discard[4096];
+	while (chunk.size > sizeof(discard)) {
+		readExpect(discard, sizeof(discard), "chunk data");
+		chunk.size -= sizeof(discard);
+	}
+	if (chunk.size) readExpect(discard, chunk.size, "chunk data");
+	readCrc();
+}
+
+static struct PACKED {
+	uint32_t width;
+	uint32_t height;
+	uint8_t depth;
+	enum PACKED {
+		Grayscale      = 0,
+		Truecolor      = 2,
+		Indexed        = 3,
+		GrayscaleAlpha = 4,
+		TruecolorAlpha = 6,
+	} color;
+	enum PACKED { Deflate } compression;
+	enum PACKED { Adaptive } filter;
+	enum PACKED { Progressive, Adam7 } interlace;
+} header;
+_Static_assert(13 == sizeof(header), "header size");
+
+static size_t pixelBits(void) {
+	switch (header.color) {
+		case Grayscale:      return 1 * header.depth;
+		case Truecolor:      return 3 * header.depth;
+		case Indexed:        return 1 * header.depth;
+		case GrayscaleAlpha: return 2 * header.depth;
+		case TruecolorAlpha: return 4 * header.depth;
+		default: abort();
+	}
+}
+
+static size_t pixelSize(void) {
+	return (pixelBits() + 7) / 8;
+}
+
+static size_t lineSize(void) {
+	return (header.width * pixelBits() + 7) / 8;
+}
+
+static size_t dataSize(void) {
+	return (1 + lineSize()) * header.height;
+}
+
+static const char *ColorStr[] = {
+	[Grayscale] = "grayscale",
+	[Truecolor] = "truecolor",
+	[Indexed] = "indexed",
+	[GrayscaleAlpha] = "grayscale alpha",
+	[TruecolorAlpha] = "truecolor alpha",
+};
+static void printHeader(void) {
+	fprintf(
+		stderr,
+		"%s: %ux%u %hhu-bit %s\n",
+		path,
+		header.width, header.height,
+		header.depth, ColorStr[header.color]
+	);
+}
+
+static void readHeader(struct Chunk chunk) {
+	if (chunk.size != sizeof(header)) {
+		errx(
+			EX_DATAERR, "%s: expected IHDR size %zu, found %u",
+			path, sizeof(header), chunk.size
+		);
+	}
+	readExpect(&header, sizeof(header), "header");
+	readCrc();
+
+	header.width = ntohl(header.width);
+	header.height = ntohl(header.height);
+
+	if (!header.width) errx(EX_DATAERR, "%s: invalid width 0", path);
+	if (!header.height) errx(EX_DATAERR, "%s: invalid height 0", path);
+	switch (PAIR(header.color, header.depth)) {
+		case PAIR(Grayscale, 1):
+		case PAIR(Grayscale, 2):
+		case PAIR(Grayscale, 4):
+		case PAIR(Grayscale, 8):
+		case PAIR(Grayscale, 16):
+		case PAIR(Truecolor, 8):
+		case PAIR(Truecolor, 16):
+		case PAIR(Indexed, 1):
+		case PAIR(Indexed, 2):
+		case PAIR(Indexed, 4):
+		case PAIR(Indexed, 8):
+		case PAIR(GrayscaleAlpha, 8):
+		case PAIR(GrayscaleAlpha, 16):
+		case PAIR(TruecolorAlpha, 8):
+		case PAIR(TruecolorAlpha, 16):
+			break;
+		default:
+			errx(
+				EX_DATAERR, "%s: invalid color type %hhu and bit depth %hhu",
+				path, header.color, header.depth
+			);
+	}
+	if (header.compression != Deflate) {
+		errx(
+			EX_DATAERR, "%s: invalid compression method %hhu",
+			path, header.compression
+		);
+	}
+	if (header.filter != Adaptive) {
+		errx(EX_DATAERR, "%s: invalid filter method %hhu", path, header.filter);
+	}
+	if (header.interlace > Adam7) {
+		errx(EX_DATAERR, "%s: invalid interlace method %hhu", path, header.interlace);
+	}
+
+	if (verbose) printHeader();
+}
+
+static void writeHeader(void) {
+	if (verbose) printHeader();
+
+	struct Chunk ihdr = { .size = sizeof(header), .type = "IHDR" };
+	writeChunk(ihdr);
+	header.width = htonl(header.width);
+	header.height = htonl(header.height);
+	writeExpect(&header, sizeof(header));
+	writeCrc();
+
+	header.width = ntohl(header.width);
+	header.height = ntohl(header.height);
+}
+
+static struct {
+	uint32_t len;
+	uint8_t entries[256][3];
+} palette;
+
+static struct {
+	uint32_t len;
+	uint8_t alpha[256];
+} trans;
+
+static void paletteClear(void) {
+	palette.len = 0;
+	trans.len = 0;
+}
+
+static uint32_t paletteIndex(bool alpha, const uint8_t *rgba) {
+	uint32_t i;
+	for (i = 0; i < palette.len; ++i) {
+		if (alpha && i < trans.len && trans.alpha[i] != rgba[3]) continue;
+		if (0 == memcmp(palette.entries[i], rgba, 3)) break;
+	}
+	return i;
+}
+
+static bool paletteAdd(bool alpha, const uint8_t *rgba) {
+	uint32_t i = paletteIndex(alpha, rgba);
+	if (i < palette.len) return true;
+	if (i == 256) return false;
+	memcpy(palette.entries[i], rgba, 3);
+	palette.len++;
+	if (alpha) {
+		trans.alpha[i] = rgba[3];
+		trans.len++;
+	}
+	return true;
+}
+
+static void transCompact(void) {
+	uint32_t i;
+	for (i = 0; i < trans.len; ++i) {
+		if (trans.alpha[i] == 0xFF) break;
+	}
+	if (i == trans.len) return;
+
+	for (uint32_t j = i + 1; j < trans.len; ++j) {
+		if (trans.alpha[j] == 0xFF) continue;
+
+		uint8_t alpha = trans.alpha[i];
+		trans.alpha[i] = trans.alpha[j];
+		trans.alpha[j] = alpha;
+
+		uint8_t rgb[3];
+		memcpy(rgb, palette.entries[i], 3);
+		memcpy(palette.entries[i], palette.entries[j], 3);
+		memcpy(palette.entries[j], rgb, 3);
+
+		i++;
+	}
+	trans.len = i;
+}
+
+static void readPalette(struct Chunk chunk) {
+	if (chunk.size % 3) {
+		errx(EX_DATAERR, "%s: PLTE size %u not divisible by 3", path, chunk.size);
+	}
+
+	palette.len = chunk.size / 3;
+	if (palette.len > 256) {
+		errx(EX_DATAERR, "%s: PLTE length %u > 256", path, palette.len);
+	}
+
+	readExpect(palette.entries, chunk.size, "palette data");
+	readCrc();
+
+	if (verbose) fprintf(stderr, "%s: palette length %u\n", path, palette.len);
+}
+
+static void writePalette(void) {
+	if (verbose) fprintf(stderr, "%s: palette length %u\n", path, palette.len);
+	struct Chunk plte = { .size = 3 * palette.len, .type = "PLTE" };
+	writeChunk(plte);
+	writeExpect(palette.entries, plte.size);
+	writeCrc();
+}
+
+static void readTrans(struct Chunk chunk) {
+	trans.len = chunk.size;
+	if (trans.len > 256) {
+		errx(EX_DATAERR, "%s: tRNS length %u > 256", path, trans.len);
+	}
+	readExpect(trans.alpha, chunk.size, "transparency alpha");
+	readCrc();
+	if (verbose) fprintf(stderr, "%s: transparency length %u\n", path, trans.len);
+}
+
+static void writeTrans(void) {
+	if (verbose) fprintf(stderr, "%s: transparency length %u\n", path, trans.len);
+	struct Chunk trns = { .size = trans.len, .type = "tRNS" };
+	writeChunk(trns);
+	writeExpect(trans.alpha, trns.size);
+	writeCrc();
+}
+
+static uint8_t *data;
+
+static void allocData(void) {
+	data = malloc(dataSize());
+	if (!data) err(EX_OSERR, "malloc(%zu)", dataSize());
+}
+
+static void readData(struct Chunk chunk) {
+	if (verbose) fprintf(stderr, "%s: data size %zu\n", path, dataSize());
+
+	struct z_stream_s stream = { .next_out = data, .avail_out = dataSize() };
+	int error = inflateInit(&stream);
+	if (error != Z_OK) errx(EX_SOFTWARE, "%s: inflateInit: %s", path, stream.msg);
+
+	for (;;) {
+		if (0 != memcmp(chunk.type, "IDAT", 4)) {
+			errx(EX_DATAERR, "%s: missing IDAT chunk", path);
+		}
+
+		uint8_t *idat = malloc(chunk.size);
+		if (!idat) err(EX_OSERR, "malloc");
+
+		readExpect(idat, chunk.size, "image data");
+		readCrc();
+
+		stream.next_in = idat;
+		stream.avail_in = chunk.size;
+		int error = inflate(&stream, Z_SYNC_FLUSH);
+		free(idat);
+
+		if (error == Z_STREAM_END) break;
+		if (error != Z_OK) {
+			errx(EX_DATAERR, "%s: inflate: %s", path, stream.msg);
+		}
+
+		chunk = readChunk();
+	}
+
+	inflateEnd(&stream);
+	if ((size_t)stream.total_out != dataSize()) {
+		errx(
+			EX_DATAERR, "%s: expected data size %zu, found %zu",
+			path, dataSize(), (size_t)stream.total_out
+		);
+	}
+
+	if (verbose) {
+		fprintf(
+			stderr, "%s: deflate size %zu\n", path, (size_t)stream.total_in
+		);
+	}
+}
+
+static void writeData(void) {
+	if (verbose) fprintf(stderr, "%s: data size %zu\n", path, dataSize());
+
+	uLong size = compressBound(dataSize());
+	uint8_t *deflate = malloc(size);
+	if (!deflate) err(EX_OSERR, "malloc");
+
+	int error = compress2(deflate, &size, data, dataSize(), Z_BEST_COMPRESSION);
+	if (error != Z_OK) errx(EX_SOFTWARE, "%s: compress2: %d", path, error);
+
+	struct Chunk idat = { .size = size, .type = "IDAT" };
+	writeChunk(idat);
+	writeExpect(deflate, size);
+	writeCrc();
+
+	free(deflate);
+
+	if (verbose) fprintf(stderr, "%s: deflate size %lu\n", path, size);
+}
+
+static void writeEnd(void) {
+	struct Chunk iend = { .size = 0, .type = "IEND" };
+	writeChunk(iend);
+	writeCrc();
+}
+
+enum PACKED Filter {
+	None,
+	Sub,
+	Up,
+	Average,
+	Paeth,
+	FilterCount,
+};
+
+struct Bytes {
+	uint8_t x;
+	uint8_t a;
+	uint8_t b;
+	uint8_t c;
+};
+
+static uint8_t paethPredictor(struct Bytes f) {
+	int32_t p = (int32_t)f.a + (int32_t)f.b - (int32_t)f.c;
+	int32_t pa = abs(p - (int32_t)f.a);
+	int32_t pb = abs(p - (int32_t)f.b);
+	int32_t pc = abs(p - (int32_t)f.c);
+	if (pa <= pb && pa <= pc) return f.a;
+	if (pb <= pc) return f.b;
+	return f.c;
+}
+
+static uint8_t recon(enum Filter type, struct Bytes f) {
+	switch (type) {
+		case None:    return f.x;
+		case Sub:     return f.x + f.a;
+		case Up:      return f.x + f.b;
+		case Average: return f.x + ((uint32_t)f.a + (uint32_t)f.b) / 2;
+		case Paeth:   return f.x + paethPredictor(f);
+		default:      abort();
+	}
+}
+
+static uint8_t filt(enum Filter type, struct Bytes f) {
+	switch (type) {
+		case None:    return f.x;
+		case Sub:     return f.x - f.a;
+		case Up:      return f.x - f.b;
+		case Average: return f.x - ((uint32_t)f.a + (uint32_t)f.b) / 2;
+		case Paeth:   return f.x - paethPredictor(f);
+		default:      abort();
+	}
+}
+
+static struct Line {
+	enum Filter type;
+	uint8_t data[];
+} **lines;
+
+static void allocLines(void) {
+	lines = calloc(header.height, sizeof(*lines));
+	if (!lines) err(EX_OSERR, "calloc(%u, %zu)", header.height, sizeof(*lines));
+}
+
+static void scanlines(void) {
+	size_t stride = 1 + lineSize();
+	for (uint32_t y = 0; y < header.height; ++y) {
+		lines[y] = (struct Line *)&data[y * stride];
+		if (lines[y]->type >= FilterCount) {
+			errx(EX_DATAERR, "%s: invalid filter type %hhu", path, lines[y]->type);
+		}
+	}
+}
+
+static struct Bytes origBytes(uint32_t y, size_t i) {
+	bool a = (i >= pixelSize()), b = (y > 0), c = (a && b);
+	return (struct Bytes) {
+		.x = lines[y]->data[i],
+		.a = a ? lines[y]->data[i - pixelSize()] : 0,
+		.b = b ? lines[y - 1]->data[i] : 0,
+		.c = c ? lines[y - 1]->data[i - pixelSize()] : 0,
+	};
+}
+
+static void reconData(void) {
+	for (uint32_t y = 0; y < header.height; ++y) {
+		for (size_t i = 0; i < lineSize(); ++i) {
+			lines[y]->data[i] =
+				recon(lines[y]->type, origBytes(y, i));
+		}
+		lines[y]->type = None;
+	}
+}
+
+static void filterData(void) {
+	if (header.color == Indexed || header.depth < 8) return;
+	for (uint32_t y = header.height - 1; y < header.height; --y) {
+		uint8_t filter[FilterCount][lineSize()];
+		uint32_t heuristic[FilterCount] = {0};
+		enum Filter minType = None;
+		for (enum Filter type = None; type < FilterCount; ++type) {
+			for (size_t i = 0; i < lineSize(); ++i) {
+				filter[type][i] = filt(type, origBytes(y, i));
+				heuristic[type] += abs((int8_t)filter[type][i]);
+			}
+			if (heuristic[type] < heuristic[minType]) minType = type;
+		}
+		lines[y]->type = minType;
+		memcpy(lines[y]->data, filter[minType], lineSize());
+	}
+}
+
+static void discardAlpha(void) {
+	if (header.color != GrayscaleAlpha && header.color != TruecolorAlpha) return;
+	size_t sampleSize = header.depth / 8;
+	size_t colorSize = pixelSize() - sampleSize;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		for (uint32_t x = 0; x < header.width; ++x) {
+			for (size_t i = 0; i < sampleSize; ++i) {
+				if (lines[y]->data[x * pixelSize() + colorSize + i] != 0xFF) return;
+			}
+		}
+	}
+
+	uint8_t *ptr = data;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		*ptr++ = lines[y]->type;
+		for (uint32_t x = 0; x < header.width; ++x) {
+			memmove(ptr, &lines[y]->data[x * pixelSize()], colorSize);
+			ptr += colorSize;
+		}
+	}
+	header.color = (header.color == GrayscaleAlpha) ? Grayscale : Truecolor;
+	scanlines();
+}
+
+static void discardColor(void) {
+	if (header.color != Truecolor && header.color != TruecolorAlpha) return;
+	size_t sampleSize = header.depth / 8;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		for (uint32_t x = 0; x < header.width; ++x) {
+			uint8_t *r = &lines[y]->data[x * pixelSize()];
+			uint8_t *g = r + sampleSize;
+			uint8_t *b = g + sampleSize;
+			if (0 != memcmp(r, g, sampleSize)) return;
+			if (0 != memcmp(g, b, sampleSize)) return;
+		}
+	}
+
+	uint8_t *ptr = data;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		*ptr++ = lines[y]->type;
+		for (uint32_t x = 0; x < header.width; ++x) {
+			uint8_t *pixel = &lines[y]->data[x * pixelSize()];
+			memmove(ptr, pixel, sampleSize);
+			ptr += sampleSize;
+			if (header.color == TruecolorAlpha) {
+				memmove(ptr, pixel + 3 * sampleSize, sampleSize);
+				ptr += sampleSize;
+			}
+		}
+	}
+	header.color = (header.color == Truecolor) ? Grayscale : GrayscaleAlpha;
+	scanlines();
+}
+
+static void indexColor(void) {
+	if (header.color != Truecolor && header.color != TruecolorAlpha) return;
+	if (header.depth != 8) return;
+	bool alpha = (header.color == TruecolorAlpha);
+	for (uint32_t y = 0; y < header.height; ++y) {
+		for (uint32_t x = 0; x < header.width; ++x) {
+			if (!paletteAdd(alpha, &lines[y]->data[x * pixelSize()])) return;
+		}
+	}
+	transCompact();
+
+	uint8_t *ptr = data;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		*ptr++ = lines[y]->type;
+		for (uint32_t x = 0; x < header.width; ++x) {
+			*ptr++ = paletteIndex(alpha, &lines[y]->data[x * pixelSize()]);
+		}
+	}
+	header.color = Indexed;
+	scanlines();
+}
+
+static void reduceDepth8(void) {
+	if (header.color != Grayscale && header.color != Indexed) return;
+	if (header.depth != 8) return;
+	if (header.color == Grayscale) {
+		for (uint32_t y = 0; y < header.height; ++y) {
+			for (size_t i = 0; i < lineSize(); ++i) {
+				uint8_t a = lines[y]->data[i];
+				if ((a >> 4) != (a & 0x0F)) return;
+			}
+		}
+	} else if (palette.len > 16) {
+		return;
+	}
+
+	uint8_t *ptr = data;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		*ptr++ = lines[y]->type;
+		for (size_t i = 0; i < lineSize(); i += 2) {
+			uint8_t iByte = lines[y]->data[i];
+			uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0;
+			uint8_t a = iByte & 0x0F;
+			uint8_t b = jByte & 0x0F;
+			*ptr++ = a << 4 | b;
+		}
+	}
+	header.depth = 4;
+	scanlines();
+}
+
+static void reduceDepth4(void) {
+	if (header.depth != 4) return;
+	if (header.color == Grayscale) {
+		for (uint32_t y = 0; y < header.height; ++y) {
+			for (size_t i = 0; i < lineSize(); ++i) {
+				uint8_t a = lines[y]->data[i] >> 4;
+				uint8_t b = lines[y]->data[i] & 0x0F;
+				if ((a >> 2) != (a & 0x03)) return;
+				if ((b >> 2) != (b & 0x03)) return;
+			}
+		}
+	} else if (palette.len > 4) {
+		return;
+	}
+
+	uint8_t *ptr = data;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		*ptr++ = lines[y]->type;
+		for (size_t i = 0; i < lineSize(); i += 2) {
+			uint8_t iByte = lines[y]->data[i];
+			uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0;
+			uint8_t a = iByte >> 4 & 0x03, b = iByte & 0x03;
+			uint8_t c = jByte >> 4 & 0x03, d = jByte & 0x03;
+			*ptr++ = a << 6 | b << 4 | c << 2 | d;
+		}
+	}
+	header.depth = 2;
+	scanlines();
+}
+
+static void reduceDepth2(void) {
+	if (header.depth != 2) return;
+	if (header.color == Grayscale) {
+		for (uint32_t y = 0; y < header.height; ++y) {
+			for (size_t i = 0; i < lineSize(); ++i) {
+				uint8_t a = lines[y]->data[i] >> 6;
+				uint8_t b = lines[y]->data[i] >> 4 & 0x03;
+				uint8_t c = lines[y]->data[i] >> 2 & 0x03;
+				uint8_t d = lines[y]->data[i] & 0x03;
+				if ((a >> 1) != (a & 0x01)) return;
+				if ((b >> 1) != (b & 0x01)) return;
+				if ((c >> 1) != (c & 0x01)) return;
+				if ((d >> 1) != (d & 0x01)) return;
+			}
+		}
+	} else if (palette.len > 2) {
+		return;
+	}
+
+	uint8_t *ptr = data;
+	for (uint32_t y = 0; y < header.height; ++y) {
+		*ptr++ = lines[y]->type;
+		for (size_t i = 0; i < lineSize(); i += 2) {
+			uint8_t iByte = lines[y]->data[i];
+			uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0;
+			uint8_t a = iByte >> 6 & 0x01, b = iByte >> 4 & 0x01;
+			uint8_t c = iByte >> 2 & 0x01, d = iByte & 0x01;
+			uint8_t e = jByte >> 6 & 0x01, f = jByte >> 4 & 0x01;
+			uint8_t g = jByte >> 2 & 0x01, h = jByte & 0x01;
+			*ptr++ = a << 7 | b << 6 | c << 5 | d << 4 | e << 3 | f << 2 | g << 1 | h;
+		}
+	}
+	header.depth = 1;
+	scanlines();
+}
+
+static void reduceDepth(void) {
+	reduceDepth8();
+	reduceDepth4();
+	reduceDepth2();
+}
+
+static void optimize(const char *inPath, const char *outPath) {
+	if (inPath) {
+		path = inPath;
+		file = fopen(path, "r");
+		if (!file) err(EX_NOINPUT, "%s", path);
+	} else {
+		path = "(stdin)";
+		file = stdin;
+	}
+
+	readSignature();
+	struct Chunk ihdr = readChunk();
+	if (0 != memcmp(ihdr.type, "IHDR", 4)) {
+		errx(EX_DATAERR, "%s: expected IHDR, found %s", path, typeStr(ihdr));
+	}
+	readHeader(ihdr);
+	if (header.interlace != Progressive) {
+		errx(
+			EX_CONFIG, "%s: unsupported interlace method %hhu",
+			path, header.interlace
+		);
+	}
+
+	paletteClear();
+	allocData();
+	for (;;) {
+		struct Chunk chunk = readChunk();
+		if (0 == memcmp(chunk.type, "PLTE", 4)) {
+			readPalette(chunk);
+		} else if (0 == memcmp(chunk.type, "tRNS", 4)) {
+			readTrans(chunk);
+		} else if (0 == memcmp(chunk.type, "IDAT", 4)) {
+			readData(chunk);
+		} else if (0 != memcmp(chunk.type, "IEND", 4)) {
+			skipChunk(chunk);
+		} else {
+			break;
+		}
+	}
+
+	fclose(file);
+
+	allocLines();
+	scanlines();
+	reconData();
+
+	discardAlpha();
+	discardColor();
+	indexColor();
+	reduceDepth();
+	filterData();
+	free(lines);
+
+	if (outPath) {
+		path = outPath;
+		file = fopen(path, "w");
+		if (!file) err(EX_CANTCREAT, "%s", path);
+	} else {
+		path = "(stdout)";
+		file = stdout;
+	}
+
+	writeSignature();
+	writeHeader();
+	if (header.color == Indexed) {
+		writePalette();
+		if (trans.len) writeTrans();
+	}
+	writeData();
+	writeEnd();
+	free(data);
+
+	int error = fclose(file);
+	if (error) err(EX_IOERR, "%s", path);
+}
+
+int main(int argc, char *argv[]) {
+	bool stdio = false;
+	char *output = NULL;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "co:v"))) {
+		switch (opt) {
+			break; case 'c': stdio = true;
+			break; case 'o': output = optarg;
+			break; case 'v': verbose = true;
+			break; default: return EX_USAGE;
+		}
+	}
+
+	if (argc - optind == 1 && (output || stdio)) {
+		optimize(argv[optind], output);
+	} else if (optind < argc) {
+		for (int i = optind; i < argc; ++i) {
+			optimize(argv[i], argv[i]);
+		}
+	} else {
+		optimize(NULL, output);
+	}
+
+	return EX_OK;
+}
diff --git a/bin/psf2png.c b/bin/psf2png.c
new file mode 100644
index 00000000..c36238a0
--- /dev/null
+++ b/bin/psf2png.c
@@ -0,0 +1,107 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "png.h"
+
+int main(int argc, char *argv[]) {
+	uint32_t cols = 32;
+	const char *str = NULL;
+	uint32_t fg = 0xFFFFFF;
+	uint32_t bg = 0x000000;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "b:c:f:s:"))) {
+		switch (opt) {
+			break; case 'b': bg = strtoul(optarg, NULL, 16);
+			break; case 'c': cols = strtoul(optarg, NULL, 0);
+			break; case 'f': fg = strtoul(optarg, NULL, 16);
+			break; case 's': str = optarg;
+			break; default:  return EX_USAGE;
+		}
+	}
+	if (!cols && str) cols = strlen(str);
+	if (!cols) return EX_USAGE;
+
+	const char *path = NULL;
+	if (optind < argc) path = argv[optind];
+	
+	FILE *file = path ? fopen(path, "r") : stdin;
+	if (!file) err(EX_NOINPUT, "%s", path);
+	if (!path) path = "(stdin)";
+
+	struct {
+		uint32_t magic;
+		uint32_t version;
+		uint32_t size;
+		uint32_t flags;
+		struct {
+			uint32_t len;
+			uint32_t size;
+			uint32_t height;
+			uint32_t width;
+		} glyph;
+	} header;
+	size_t len = fread(&header, sizeof(header), 1, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+	if (len < 1) errx(EX_DATAERR, "%s: truncated header", path);
+
+	uint32_t widthBytes = (header.glyph.width + 7) / 8;
+	uint8_t glyphs[header.glyph.len][header.glyph.height][widthBytes];
+	len = fread(glyphs, header.glyph.size, header.glyph.len, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+	if (len < header.glyph.len) {
+		errx(EX_DATAERR, "%s: truncated glyphs", path);
+	}
+	fclose(file);
+
+	uint32_t count = (str ? strlen(str) : header.glyph.len);
+	uint32_t width = header.glyph.width * cols;
+	uint32_t rows = (count + cols - 1) / cols;
+	uint32_t height = header.glyph.height * rows;
+
+	pngHead(stdout, width, height, 8, PNGIndexed);
+	uint8_t pal[] = {
+		bg >> 16, bg >> 8, bg,
+		fg >> 16, fg >> 8, fg,
+	};
+	pngPalette(stdout, pal, sizeof(pal));
+
+	uint8_t data[height][1 + width];
+	memset(data, PNGNone, sizeof(data));
+
+	for (uint32_t i = 0; i < count; ++i) {
+		uint32_t row = header.glyph.height * (i / cols);
+		uint32_t col = 1 + header.glyph.width * (i % cols);
+		uint32_t g = (str ? str[i] : i);
+		for (uint32_t y = 0; y < header.glyph.height; ++y) {
+			for (uint32_t x = 0; x < header.glyph.width; ++x) {
+				uint8_t bit = glyphs[g][y][x / 8] >> (7 - x % 8) & 1;
+				data[row + y][col + x] = bit;
+			}
+		}
+	}
+
+	pngData(stdout, (uint8_t *)data, sizeof(data));
+	pngTail(stdout);
+}
diff --git a/bin/psfed.c b/bin/psfed.c
new file mode 100644
index 00000000..3f72816a
--- /dev/null
+++ b/bin/psfed.c
@@ -0,0 +1,577 @@
+/* Copyright (C) 2018  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fb.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
+#include <wchar.h>
+
+static const wchar_t CP437[256] =
+	L"\0☺☻♥♦♣♠•◘○◙♂♀♪♫☼"
+	L"►◄↕‼¶§▬↨↑↓→â†âˆŸâ†”▲▼"
+	L" !\"#$%&'()*+,-./"
+	L"0123456789:;<=>?"
+	L"@ABCDEFGHIJKLMNO"
+	L"PQRSTUVWXYZ[\\]^_"
+	L"`abcdefghijklmno"
+	L"pqrstuvwxyz{|}~⌂"
+	L"ÇüéâäàåçêëèïîìÄÅ"
+	L"ÉæÆôöòûùÿÖÜ¢£¥₧ƒ"
+	L"áíóúñѪº¿âŒÂ¬Â½Â¼Â¡Â«Â»"
+	L"░▒▓│┤╡╢╖╕╣║╗â•â•œâ•›â”"
+	L"└┴┬├─┼╞╟╚╔╩╦╠â•â•¬â•§"
+	L"╨╤╥╙╘╒╓╫╪┘┌█▄▌â–â–€"
+	L"αßΓπΣσµτΦΘΩδ∞φε∩"
+	L"≡±≥≤⌠⌡÷≈°∙·√â¿Â²â– \0";
+
+static struct {
+	uint32_t width;
+	uint32_t height;
+	uint32_t *buffer;
+	uint32_t background;
+} frame;
+
+static void frameClear(void) {
+	for (uint32_t i = 0; i < frame.width * frame.height; ++i) {
+		frame.buffer[i] = frame.background;
+	}
+}
+
+static void frameOpen(void) {
+	const char *dev = getenv("FRAMEBUFFER");
+	if (!dev) dev = "/dev/fb0";
+
+	int fd = open(dev, O_RDWR);
+	if (fd < 0) err(EX_OSFILE, "%s", dev);
+
+	struct fb_var_screeninfo info;
+	int error = ioctl(fd, FBIOGET_VSCREENINFO, &info);
+	if (error) err(EX_IOERR, "%s", dev);
+
+	frame.width = info.xres;
+	frame.height = 3 * info.yres / 4;
+	frame.buffer = mmap(
+		NULL, sizeof(*frame.buffer) * frame.width * frame.height,
+		PROT_READ | PROT_WRITE, MAP_SHARED,
+		fd, 0
+	);
+	if (frame.buffer == MAP_FAILED) err(EX_IOERR, "%s", dev);
+	close(fd);
+
+	frame.background = frame.buffer[0];
+	atexit(frameClear);
+}
+
+static const uint32_t Magic = 0x864AB572;
+static const uint32_t Version = 0;
+static const uint32_t FlagUnicode = 1 << 0;
+static uint32_t bytes(uint32_t bits) {
+	return (bits + 7) / 8;
+}
+
+static char *path;
+static struct {
+	uint32_t magic;
+	uint32_t version;
+	uint32_t size;
+	uint32_t flags;
+	struct {
+		uint32_t len;
+		uint32_t size;
+		uint32_t height;
+		uint32_t width;
+	} glyph;
+} header;
+static uint8_t *glyphs;
+
+static void fileRead(uint32_t newLen, uint32_t newWidth, uint32_t newHeight) {
+	FILE *file = fopen(path, "r");
+	if (file) {
+		size_t len = fread(&header, sizeof(header), 1, file);
+		if (ferror(file)) err(EX_IOERR, "%s", path);
+		if (len < 1) errx(EX_DATAERR, "%s: truncated header", path);
+
+	} else {
+		if (errno != ENOENT) err(EX_NOINPUT, "%s", path);
+		header.magic = Magic;
+		header.version = Version;
+		header.size = sizeof(header);
+		header.flags = 0;
+		header.glyph.len = newLen;
+		header.glyph.size = bytes(newWidth) * newHeight;
+		header.glyph.height = newHeight;
+		header.glyph.width = newWidth;
+	}
+
+	if (header.magic != Magic) {
+		errx(EX_DATAERR, "%s: invalid magic %08X", path, header.magic);
+	}
+	if (header.version != Version) {
+		errx(EX_DATAERR, "%s: unsupported version %u", path, header.version);
+	}
+	if (header.flags & FlagUnicode) {
+		errx(EX_DATAERR, "%s: unsupported unicode table", path);
+	}
+	if (header.flags) {
+		errx(EX_DATAERR, "%s: unsupported flags %08X", path, header.flags);
+	}
+
+	if (file && header.size > sizeof(header)) {
+		int error = fseek(file, header.size, SEEK_SET);
+		if (error) err(EX_IOERR, "%s", path);
+
+		warnx("%s: truncating long header", path);
+		header.size = sizeof(header);
+	}
+
+	glyphs = calloc(header.glyph.len, header.glyph.size);
+	if (!glyphs) err(EX_OSERR, "calloc");
+
+	if (file) {
+		size_t len = fread(glyphs, header.glyph.size, header.glyph.len, file);
+		if (ferror(file)) err(EX_IOERR, "%s", path);
+		if (len < header.glyph.len) {
+			errx(EX_DATAERR, "%s: truncated glyphs", path);
+		}
+		fclose(file);
+	}
+}
+
+static void fileWrite(void) {
+	FILE *file = fopen(path, "w");
+	if (!file) err(EX_CANTCREAT, "%s", path);
+
+	fwrite(&header, sizeof(header), 1, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+
+	fwrite(glyphs, header.glyph.size, header.glyph.len, file);
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+
+	int error = fclose(file);
+	if (error) err(EX_IOERR, "%s", path);
+}
+
+static uint8_t *glyph(uint32_t index) {
+	return &glyphs[header.glyph.size * index];
+}
+static uint8_t *bitByte(uint32_t index, uint32_t x, uint32_t y) {
+	return &glyph(index)[bytes(header.glyph.width) * y + x / 8];
+}
+static uint8_t bitGet(uint32_t index, uint32_t x, uint32_t y) {
+	return *bitByte(index, x, y) >> (7 - x % 8) & 1;
+}
+static void bitFlip(uint32_t index, uint32_t x, uint32_t y) {
+	*bitByte(index, x, y) ^= 1 << (7 - x % 8);
+}
+static void bitSet(uint32_t index, uint32_t x, uint32_t y, uint8_t bit) {
+	*bitByte(index, x, y) &= ~(1 << (7 - x % 8));
+	*bitByte(index, x, y) |= bit << (7 - x % 8);
+}
+
+static void drawGlyph(
+	uint32_t destX, uint32_t destY, uint32_t scale, uint32_t index,
+	uint32_t selectX, uint32_t selectY, uint32_t guideX, uint32_t guideY
+) {
+	destX <<= scale;
+	destY <<= scale;
+
+	for (uint32_t y = 0; y < (header.glyph.height << scale); ++y) {
+		if (destY + y >= frame.height) break;
+		for (uint32_t x = 0; x < (header.glyph.width << scale); ++x) {
+			if (destX + x >= frame.width) break;
+
+			uint32_t glyphX = x >> scale;
+			uint32_t glyphY = y >> scale;
+			uint32_t fill = -bitGet(index, glyphX, glyphY);
+			if (selectX & 1 << glyphX && selectY & 1 << glyphY) fill ^= 0x77;
+			if (guideX & 1 << glyphX || guideY & 1 << glyphY) fill ^= 0x3300;
+
+			frame.buffer[frame.width * (destY + y) + destX + x] = fill;
+		}
+	}
+}
+
+static void drawBorder(uint32_t destX, uint32_t destY, uint32_t scale) {
+	destX <<= scale;
+	destY <<= scale;
+
+	for (uint32_t y = 0; y < destY; ++y) {
+		if (y >= frame.height) break;
+		uint32_t fill = -(y >> scale & 1) ^ 0x555555;
+		for (uint32_t x = 0; x < (uint32_t)(1 << scale); ++x) {
+			if (destX + x >= frame.width) break;
+			frame.buffer[frame.width * y + destX + x] = fill;
+		}
+	}
+
+	for (uint32_t x = 0; x < destX; ++x) {
+		if (x >= frame.width) break;
+		uint32_t fill = -(x >> scale & 1) ^ 0x555555;
+		for (uint32_t y = 0; y < (uint32_t)(1 << scale); ++y) {
+			if (destY + y >= frame.height) break;
+			frame.buffer[frame.width * (destY + y) + x] = fill;
+		}
+	}
+}
+
+enum { LF = '\n', Esc = '\33', Del = '\177' };
+
+static enum {
+	Normal,
+	Edit,
+	Preview,
+	Discard,
+} mode;
+
+static struct {
+	uint32_t scale;
+	uint32_t index;
+	bool modified;
+	bool to;
+	uint32_t from;
+} normal;
+
+static struct {
+	uint32_t scale;
+	uint32_t index;
+	uint32_t x;
+	uint32_t y;
+	uint32_t guideX;
+	uint32_t guideY;
+	uint8_t *undo;
+	uint8_t *copy;
+} edit = {
+	.scale = 4,
+};
+
+static const uint32_t NormalCols = 32;
+static void drawNormal(void) {
+	for (uint32_t i = 0; i < header.glyph.len; ++i) {
+		drawGlyph(
+			header.glyph.width * (i % NormalCols),
+			header.glyph.height * (i  / NormalCols),
+			normal.scale, i,
+			-(i == normal.index), -(i == normal.index), 0, 0
+		);
+	}
+}
+
+static void normalDec(uint32_t n) {
+	if (normal.index >= n) normal.index -= n;
+}
+static void normalInc(uint32_t n) {
+	if (normal.index + n < header.glyph.len) normal.index += n;
+}
+static void normalPrint(const char *prefix) {
+	if (normal.index <= 256) {
+		printf(
+			"%s: %02X '%lc'\n",
+			prefix, normal.index, (wint_t)CP437[normal.index]
+		);
+	} else {
+		printf("%s: %02X\n", prefix, normal.index);
+	}
+}
+
+static void inputNormal(char ch) {
+	if (normal.to) {
+		if (ch < header.glyph.len) normal.index = ch;
+		normalPrint("index");
+		normal.to = false;
+		return;
+	}
+
+	switch (ch) {
+		break; case 'q': {
+			if (!normal.modified) exit(EX_OK);
+			mode = Discard;
+		}
+		break; case 'w': {
+			fileWrite();
+			printf("write: %s\n", path);
+			normal.modified = false;
+		}
+		break; case '-': if (normal.scale) normal.scale--; frameClear();
+		break; case '+': normal.scale++;
+		break; case 'h': normalDec(1); normalPrint("index");
+		break; case 'l': normalInc(1); normalPrint("index");
+		break; case 'k': normalDec(NormalCols); normalPrint("index");
+		break; case 'j': normalInc(NormalCols); normalPrint("index");
+		break; case 'f': normal.from = normal.index; normal.to = true;
+		break; case 047: normal.index = normal.from; normalPrint("index");
+		break; case 'y': {
+			if (!edit.copy) edit.copy = malloc(header.glyph.size);
+			if (!edit.copy) err(EX_OSERR, "malloc");
+			memcpy(edit.copy, glyph(normal.index), header.glyph.size);
+			normalPrint("copy");
+		}
+		break; case 'e': {
+			normal.modified = true;
+			edit.index = normal.index;
+			if (!edit.undo) edit.undo = malloc(header.glyph.size);
+			if (!edit.undo) err(EX_OSERR, "malloc");
+			memcpy(edit.undo, glyph(edit.index), header.glyph.size);
+			mode = Edit;
+			frameClear();
+		}
+		break; case 'i': mode = Preview; frameClear();
+	}
+}
+
+static void drawEdit(void) {
+	drawGlyph(
+		0, 0, edit.scale, edit.index,
+		1 << edit.x, 1 << edit.y, edit.guideX, edit.guideY
+	);
+	drawBorder(header.glyph.width, header.glyph.height, edit.scale);
+	drawGlyph(
+		header.glyph.width << edit.scale,
+		header.glyph.height << edit.scale,
+		0, edit.index,
+		0, 0, 0, 0
+	);
+}
+
+static void inputEdit(char ch) {
+	switch (ch) {
+		break; case Esc: mode = Normal; frameClear();
+
+		break; case '-': if (edit.scale) edit.scale--; frameClear();
+		break; case '+': edit.scale++;
+		break; case 'g': edit.guideY ^= 1 << edit.y;
+		break; case 'G': edit.guideX ^= 1 << edit.x;
+
+		break; case 'h': if (edit.x) edit.x--;
+		break; case 'l': if (edit.x + 1 < header.glyph.width) edit.x++;
+		break; case 'k': if (edit.y) edit.y--;
+		break; case 'j': if (edit.y + 1 < header.glyph.height) edit.y++;
+		break; case ' ': bitFlip(edit.index, edit.x, edit.y);
+
+		break; case 'r': {
+			for (uint32_t y = 0; y < header.glyph.height; ++y) {
+				for (uint32_t x = 0; x < header.glyph.width; ++x) {
+					bitFlip(edit.index, x, y);
+				}
+			}
+		}
+
+		break; case 'H': {
+			for (uint32_t x = 0; x < header.glyph.width; ++x) {
+				for (uint32_t y = 0; y < header.glyph.height; ++y) {
+					if (x + 1 < header.glyph.width) {
+						bitSet(edit.index, x, y, bitGet(edit.index, x + 1, y));
+					} else {
+						bitSet(edit.index, x, y, 0);
+					}
+				}
+			}
+		}
+
+		break; case 'L': {
+			uint32_t width = header.glyph.width;
+			for (uint32_t x = width - 1; x < width; --x) {
+				for (uint32_t y = 0; y < header.glyph.height; ++y) {
+					if (x - 1 < width) {
+						bitSet(edit.index, x, y, bitGet(edit.index, x - 1, y));
+					} else {
+						bitSet(edit.index, x, y, 0);
+					}
+				}
+			}
+		}
+
+		break; case 'K': {
+			for (uint32_t y = 0; y < header.glyph.height; ++y) {
+				for (uint32_t x = 0; x < header.glyph.width; ++x) {
+					if (y + 1 < header.glyph.height) {
+						bitSet(edit.index, x, y, bitGet(edit.index, x, y + 1));
+					} else {
+						bitSet(edit.index, x, y, 0);
+					}
+				}
+			}
+		}
+
+		break; case 'J': {
+			uint32_t height = header.glyph.height;
+			for (uint32_t y = height - 1; y < height; --y) {
+				for (uint32_t x = 0; x < header.glyph.width; ++x) {
+					if (y - 1 < height) {
+						bitSet(edit.index, x, y, bitGet(edit.index, x, y - 1));
+					} else {
+						bitSet(edit.index, x, y, 0);
+					}
+				}
+			}
+		}
+
+		break; case 'p': {
+			if (!edit.copy) break;
+			memcpy(glyph(edit.index), edit.copy, header.glyph.size);
+		}
+		break; case 'u': {
+			if (!edit.undo) break;
+			memcpy(glyph(edit.index), edit.undo, header.glyph.size);
+		}
+	}
+}
+
+enum { PreviewRows = 8, PreviewCols = 64 };
+static struct {
+	uint32_t glyphs[PreviewRows * PreviewCols];
+	uint32_t index;
+} preview;
+
+static void drawPreview(void) {
+	for (uint32_t i = 0; i < PreviewRows * PreviewCols; ++i) {
+		drawGlyph(
+			header.glyph.width * (i % PreviewCols),
+			header.glyph.height * (i / PreviewCols),
+			0, preview.glyphs[i],
+			-(i == preview.index), -(i == preview.index), 0, 0
+		);
+	}
+}
+
+static void inputPreview(char ch) {
+	switch (ch) {
+		break; case Esc: mode = Normal; frameClear();
+		break; case Del: {
+			if (preview.index) preview.index--;
+			preview.glyphs[preview.index] = 0;
+		}
+		break; case LF: {
+			uint32_t tail = PreviewCols - (preview.index % PreviewCols);
+			memset(
+				&preview.glyphs[preview.index],
+				0, sizeof(preview.glyphs[0]) * tail
+			);
+			preview.index += tail;
+		}
+		break; default: preview.glyphs[preview.index++] = ch;
+	}
+	preview.index %= PreviewRows * PreviewCols;
+}
+
+static void drawDiscard(void) {
+	printf("discard modifications? ");
+	fflush(stdout);
+}
+
+static void inputDiscard(char ch) {
+	printf("%c\n", ch);
+	if (ch == 'Y' || ch == 'y') exit(EX_OK);
+	mode = Normal;
+}
+
+static void draw(void) {
+	switch (mode) {
+		break; case Normal: drawNormal();
+		break; case Edit: drawEdit();
+		break; case Preview: drawPreview();
+		break; case Discard: drawDiscard();
+	}
+}
+
+static void input(char ch) {
+	switch (mode) {
+		break; case Normal: inputNormal(ch);
+		break; case Edit: inputEdit(ch);
+		break; case Preview: inputPreview(ch);
+		break; case Discard: inputDiscard(ch);
+	}
+}
+
+static struct termios saveTerm;
+static void restoreTerm(void) {
+	tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm);
+}
+
+int main(int argc, char *argv[]) {
+	setlocale(LC_CTYPE, "");
+
+	uint32_t newLen = 256;
+	uint32_t newWidth = 8;
+	uint32_t newHeight = 16;
+	uint32_t setHeight = 0;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "H:g:h:w:"))) {
+		switch (opt) {
+			break; case 'H': setHeight = strtoul(optarg, NULL, 0);
+			break; case 'g': newLen = strtoul(optarg, NULL, 0);
+			break; case 'h': newHeight = strtoul(optarg, NULL, 0);
+			break; case 'w': newWidth = strtoul(optarg, NULL, 0);
+			break; default:  return EX_USAGE;
+		}
+	}
+	if (!newLen || !newWidth || !newHeight) return EX_USAGE;
+	if (optind == argc) return EX_USAGE;
+
+	path = strdup(argv[optind]);
+	fileRead(newLen, newWidth, newHeight);
+
+	if (setHeight) {
+		if (setHeight < header.glyph.height) {
+			errx(EX_CONFIG, "cannot decrease height");
+		}
+
+		uint32_t setSize = bytes(header.glyph.width) * setHeight;
+		uint8_t *setGlyphs = calloc(header.glyph.len, setSize);
+		for (uint32_t i = 0; i < header.glyph.len; ++i) {
+			memcpy(&setGlyphs[setSize * i], glyph(i), header.glyph.size);
+		}
+		free(glyphs);
+		glyphs = setGlyphs;
+
+		header.glyph.height = setHeight;
+		header.glyph.size = setSize;
+		normal.modified = true;
+	}
+
+	frameOpen();
+	frameClear();
+
+	int error = tcgetattr(STDIN_FILENO, &saveTerm);
+	if (error) err(EX_IOERR, "tcgetattr");
+	atexit(restoreTerm);
+
+	struct termios term = saveTerm;
+	term.c_lflag &= ~(ICANON | ECHO);
+	error = tcsetattr(STDIN_FILENO, TCSADRAIN, &term);
+	if (error) err(EX_IOERR, "tcsetattr");
+
+	for (;;) {
+		draw();
+		char ch;
+		ssize_t size = read(STDIN_FILENO, &ch, 1);
+		if (size < 0) err(EX_IOERR, "read");
+		if (!size) return EX_SOFTWARE;
+		input(ch);
+	}
+}
diff --git a/bin/ptee.c b/bin/ptee.c
new file mode 100644
index 00000000..6bc20fc5
--- /dev/null
+++ b/bin/ptee.c
@@ -0,0 +1,116 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <poll.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sysexits.h>
+#include <termios.h>
+#include <unistd.h>
+
+#if defined __FreeBSD__
+#include <libutil.h>
+#elif defined __linux__
+#include <pty.h>
+#else
+#include <util.h>
+#endif
+
+typedef unsigned char byte;
+
+static struct termios saveTerm;
+static void restoreTerm(void) {
+	tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm);
+}
+
+int main(int argc, char *argv[]) {
+	if (argc < 2) return EX_USAGE;
+	if (isatty(STDOUT_FILENO)) errx(EX_USAGE, "stdout is not redirected");
+
+	int error = tcgetattr(STDIN_FILENO, &saveTerm);
+	if (error) err(EX_IOERR, "tcgetattr");
+	atexit(restoreTerm);
+
+	struct termios raw = saveTerm;
+	cfmakeraw(&raw);
+	error = tcsetattr(STDIN_FILENO, TCSADRAIN, &raw);
+	if (error) err(EX_IOERR, "tcsetattr");
+
+	struct winsize window;
+	error = ioctl(STDIN_FILENO, TIOCGWINSZ, &window);
+	if (error) err(EX_IOERR, "ioctl");
+
+	int pty;
+	pid_t pid = forkpty(&pty, NULL, NULL, &window);
+	if (pid < 0) err(EX_OSERR, "forkpty");
+
+	if (!pid) {
+		execvp(argv[1], &argv[1]);
+		err(EX_NOINPUT, "%s", argv[1]);
+	}
+
+	bool stop = false;
+
+	byte buf[4096];
+	struct pollfd fds[2] = {
+		{ .events = POLLIN, .fd = STDIN_FILENO },
+		{ .events = POLLIN, .fd = pty },
+	};
+	while (0 < poll(fds, 2, -1)) {
+		if (fds[0].revents & POLLIN) {
+			ssize_t rlen = read(STDIN_FILENO, buf, sizeof(buf));
+			if (rlen < 0) err(EX_IOERR, "read");
+
+			if (rlen == 1 && buf[0] == CTRL('S')) {
+				stop ^= true;
+				continue;
+			}
+
+			if (rlen == 1 && buf[0] == CTRL('Q')) {
+				char dump[] = "\x1B[10i";
+				ssize_t wlen = write(STDOUT_FILENO, dump, sizeof(dump) - 1);
+				if (wlen < 0) err(EX_IOERR, "write");
+				continue;
+			}
+
+			ssize_t wlen = write(pty, buf, rlen);
+			if (wlen < 0) err(EX_IOERR, "write");
+		}
+
+		if (fds[1].revents & POLLIN) {
+			ssize_t rlen = read(pty, buf, sizeof(buf));
+			if (rlen < 0) err(EX_IOERR, "read");
+
+			ssize_t wlen = write(STDIN_FILENO, buf, rlen);
+			if (wlen < 0) err(EX_IOERR, "write");
+
+			if (!stop) {
+				wlen = write(STDOUT_FILENO, buf, rlen);
+				if (wlen < 0) err(EX_IOERR, "write");
+			}
+		}
+
+		int status;
+		pid_t dead = waitpid(pid, &status, WNOHANG);
+		if (dead < 0) err(EX_OSERR, "waitpid");
+		if (dead) return WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE;
+	}
+	err(EX_IOERR, "poll");
+}
diff --git a/bin/relay.c b/bin/relay.c
new file mode 100644
index 00000000..fd799462
--- /dev/null
+++ b/bin/relay.c
@@ -0,0 +1,218 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify this Program, or any covered work, by linking or
+ * combining it with LibreSSL (or a modified version of that library),
+ * containing parts covered by the terms of the OpenSSL License and the
+ * original SSLeay license, the licensors of this Program grant you
+ * additional permission to convey the resulting work. Corresponding
+ * Source for a non-source form of such a combination shall include the
+ * source code for the parts of LibreSSL used as well as that of the
+ * covered work.
+ */
+
+#include <err.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sysexits.h>
+#include <tls.h>
+#include <unistd.h>
+
+#ifdef __FreeBSD__
+#include <sys/capsicum.h>
+#endif
+
+static void clientWrite(struct tls *client, const char *ptr, size_t len) {
+	while (len) {
+		ssize_t ret = tls_write(client, ptr, len);
+		if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue;
+		if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client));
+		ptr += ret;
+		len -= ret;
+	}
+}
+
+static void clientFormat(struct tls *client, const char *format, ...) {
+	char buf[1024];
+	va_list ap;
+	va_start(ap, format);
+	int len = vsnprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+	if ((size_t)len > sizeof(buf) - 1) errx(EX_DATAERR, "message too large");
+	clientWrite(client, buf, len);
+}
+
+static void clientHandle(struct tls *client, const char *chan, char *line) {
+	char *prefix = NULL;
+	if (line[0] == ':') {
+		prefix = strsep(&line, " ") + 1;
+		if (!line) errx(EX_PROTOCOL, "unexpected eol");
+	}
+
+	char *command = strsep(&line, " ");
+	if (!strcmp(command, "001") || !strcmp(command, "INVITE")) {
+		clientFormat(client, "JOIN :%s\r\n", chan);
+	} else if (!strcmp(command, "PING")) {
+		clientFormat(client, "PONG %s\r\n", line);
+	}
+	if (strcmp(command, "PRIVMSG") && strcmp(command, "NOTICE")) return;
+
+	if (!prefix) errx(EX_PROTOCOL, "message without prefix");
+	char *nick = strsep(&prefix, "!");
+
+	if (!line) errx(EX_PROTOCOL, "message without destination");
+	char *dest = strsep(&line, " ");
+	if (strcmp(dest, chan)) return;
+
+	if (!line || line[0] != ':') errx(EX_PROTOCOL, "message without message");
+	line = &line[1];
+
+	if (!strncmp(line, "\1ACTION ", 8)) {
+		line = &line[8];
+		size_t len = strcspn(line, "\1");
+		printf("* %c\u200C%s %.*s\n", nick[0], &nick[1], (int)len, line);
+	} else if (command[0] == 'N') {
+		printf("-%c\u200C%s- %s\n", nick[0], &nick[1], line);
+	} else {
+		printf("<%c\u200C%s> %s\n", nick[0], &nick[1], line);
+	}
+}
+
+#ifdef __FreeBSD__
+static void limit(int fd, const cap_rights_t *rights) {
+	int error = cap_rights_limit(fd, rights);
+	if (error) err(EX_OSERR, "cap_rights_limit");
+}
+#endif
+
+int main(int argc, char *argv[]) {
+	int error;
+
+	if (argc < 5) return EX_USAGE;
+	const char *host = argv[1];
+	const char *port = argv[2];
+	const char *nick = argv[3];
+	const char *chan = argv[4];
+
+	setlinebuf(stdout);
+	signal(SIGPIPE, SIG_IGN);
+
+	struct tls_config *config = tls_config_new();
+	if (!config) errx(EX_SOFTWARE, "tls_config_new");
+
+	error = tls_config_set_ciphers(config, "compat");
+	if (error) {
+		errx(EX_SOFTWARE, "tls_config_set_ciphers: %s", tls_config_error(config));
+	}
+
+	struct tls *client = tls_client();
+	if (!client) errx(EX_SOFTWARE, "tls_client");
+
+	error = tls_configure(client, config);
+	if (error) errx(EX_SOFTWARE, "tls_configure: %s", tls_error(client));
+	tls_config_free(config);
+
+	struct addrinfo *head;
+	struct addrinfo hints = {
+		.ai_family = AF_UNSPEC,
+		.ai_socktype = SOCK_STREAM,
+		.ai_protocol = IPPROTO_TCP,
+	};
+	error = getaddrinfo(host, port, &hints, &head);
+	if (error) errx(EX_NOHOST, "getaddrinfo: %s", gai_strerror(error));
+
+	int sock = -1;
+	for (struct addrinfo *ai = head; ai; ai = ai->ai_next) {
+		sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+		if (sock < 0) err(EX_OSERR, "socket");
+
+		error = connect(sock, ai->ai_addr, ai->ai_addrlen);
+		if (!error) break;
+
+		close(sock);
+		sock = -1;
+	}
+	if (sock < 0) err(EX_UNAVAILABLE, "connect");
+	freeaddrinfo(head);
+
+	error = tls_connect_socket(client, sock, host);
+	if (error) errx(EX_PROTOCOL, "tls_connect: %s", tls_error(client));
+
+#ifdef __FreeBSD__
+	error = cap_enter();
+	if (error) err(EX_OSERR, "cap_enter");
+
+	cap_rights_t rights;
+	cap_rights_init(&rights, CAP_WRITE);
+	limit(STDOUT_FILENO, &rights);
+	limit(STDERR_FILENO, &rights);
+
+	cap_rights_init(&rights, CAP_EVENT, CAP_READ);
+	limit(STDIN_FILENO, &rights);
+
+	cap_rights_set(&rights, CAP_WRITE);
+	limit(sock, &rights);
+#endif
+
+	clientFormat(client, "NICK :%s\r\nUSER %s 0 * :%s\r\n", nick, nick, nick);
+
+	char *input = NULL;
+	size_t cap = 0;
+
+	char buf[4096];
+	size_t len = 0;
+
+	struct pollfd fds[2] = {
+		{ .events = POLLIN, .fd = STDIN_FILENO },
+		{ .events = POLLIN, .fd = sock },
+	};
+	while (0 < poll(fds, 2, -1)) {
+		if (fds[0].revents) {
+			ssize_t len = getline(&input, &cap, stdin);
+			if (len < 0) err(EX_IOERR, "getline");
+			input[len - 1] = '\0';
+			clientFormat(client, "NOTICE %s :%s\r\n", chan, input);
+		}
+		if (!fds[1].revents) continue;
+
+		ssize_t read = tls_read(client, &buf[len], sizeof(buf) - len);
+		if (read == TLS_WANT_POLLIN || read == TLS_WANT_POLLOUT) continue;
+		if (read < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client));
+		if (!read) return EX_UNAVAILABLE;
+		len += read;
+
+		char *crlf;
+		char *line = buf;
+		for (;;) {
+			crlf = memmem(line, &buf[len] - line, "\r\n", 2);
+			if (!crlf) break;
+			crlf[0] = '\0';
+			clientHandle(client, chan, line);
+			line = &crlf[2];
+		}
+		len -= line - buf;
+		memmove(buf, line, len);
+	}
+	err(EX_IOERR, "poll");
+}
diff --git a/bin/scheme.c b/bin/scheme.c
new file mode 100644
index 00000000..2bae8f82
--- /dev/null
+++ b/bin/scheme.c
@@ -0,0 +1,278 @@
+/* Copyright (C) 2018, 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "png.h"
+
+typedef unsigned uint;
+typedef unsigned char byte;
+
+struct HSV {
+	double h, s, v;
+};
+
+struct RGB {
+	byte r, g, b;
+};
+
+static struct RGB convert(struct HSV o) {
+	double c = o.v * o.s;
+	double h = o.h / 60.0;
+	double x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0));
+	double m = o.v - c;
+	double r = m, g = m, b = m;
+	if      (h <= 1.0) { r += c; g += x; }
+	else if (h <= 2.0) { r += x; g += c; }
+	else if (h <= 3.0) { g += c; b += x; }
+	else if (h <= 4.0) { g += x; b += c; }
+	else if (h <= 5.0) { r += x; b += c; }
+	else if (h <= 6.0) { r += c; b += x; }
+	return (struct RGB) { r * 255.0, g * 255.0, b * 255.0 };
+}
+
+static const struct HSV
+R = {   0.0, 1.0, 1.0 },
+Y = {  60.0, 1.0, 1.0 },
+G = { 120.0, 1.0, 1.0 },
+C = { 180.0, 1.0, 1.0 },
+B = { 240.0, 1.0, 1.0 },
+M = { 300.0, 1.0, 1.0 };
+
+static struct HSV x(struct HSV o, double hd, double sf, double vf) {
+	return (struct HSV) {
+		fmod(o.h + hd, 360.0),
+		fmin(o.s * sf, 1.0),
+		fmin(o.v * vf, 1.0),
+	};
+}
+
+enum {
+	Black, Red, Green, Yellow, Blue, Magenta, Cyan, White,
+	Dark = 0,
+	Light = 8,
+	Background = 16,
+	Foreground,
+	Bold,
+	Selection,
+	Cursor,
+	SchemeLen,
+};
+static struct HSV scheme[SchemeLen];
+static struct HSV *dark = &scheme[Dark];
+static struct HSV *light = &scheme[Light];
+
+static void generate(void) {
+	light[Black]   = x(R, +45.0, 0.3, 0.3);
+	light[Red]     = x(R, +10.0, 0.9, 0.8);
+	light[Green]   = x(G, -55.0, 0.8, 0.6);
+	light[Yellow]  = x(Y, -20.0, 0.8, 0.8);
+	light[Blue]    = x(B, -55.0, 0.4, 0.5);
+	light[Magenta] = x(M, +45.0, 0.4, 0.6);
+	light[Cyan]    = x(C, -60.0, 0.3, 0.6);
+	light[White]   = x(R, +45.0, 0.3, 0.8);
+
+	dark[Black] = x(light[Black], 0.0, 1.0, 0.3);
+	dark[White] = x(light[White], 0.0, 1.0, 0.75);
+	for (uint i = Red; i < White; ++i) {
+		dark[i] = x(light[i], 0.0, 1.0, 0.8);
+	}
+
+	scheme[Background] = x(dark[Black],  0.0, 1.0, 0.9);
+	scheme[Foreground] = x(light[White], 0.0, 1.0, 0.9);
+	scheme[Bold]       = x(light[White], 0.0, 1.0, 1.0);
+	scheme[Selection]  = x(light[Red], +10.0, 1.0, 0.8);
+	scheme[Cursor]     = x(dark[White],  0.0, 1.0, 0.8);
+}
+
+static void swap(struct HSV *a, struct HSV *b) {
+	struct HSV c = *a;
+	*a = *b;
+	*b = c;
+}
+
+static void invert(void) {
+	swap(&dark[Black], &light[White]);
+	swap(&dark[White], &light[Black]);
+}
+
+typedef void OutputFn(const struct HSV *hsv, uint len);
+
+static void outputHSV(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		printf("%g,%g,%g\n", hsv[i].h, hsv[i].s, hsv[i].v);
+	}
+}
+
+#define FORMAT_RGB "%02hhX%02hhX%02hhX"
+
+static void outputRGB(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		printf(FORMAT_RGB "\n", rgb.r, rgb.g, rgb.b);
+	}
+}
+
+static void outputLinux(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		printf("\x1B]P%X" FORMAT_RGB, i, rgb.r, rgb.g, rgb.b);
+	}
+}
+
+static const char *Enum[SchemeLen] = {
+	"DarkBlack", "DarkRed", "DarkGreen", "DarkYellow",
+	"DarkBlue", "DarkMagenta", "DarkCyan", "DarkWhite",
+	"LightBlack", "LightRed", "LightGreen", "LightYellow",
+	"LightBlue", "LightMagenta", "LightCyan", "LightWhite",
+	"Background", "Foreground", "Bold", "Selection", "Cursor",
+};
+
+static void outputEnum(const struct HSV *hsv, uint len) {
+	printf("enum {\n");
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		printf("\t%s = 0x" FORMAT_RGB ",\n", Enum[i], rgb.r, rgb.g, rgb.b);
+	}
+	printf("};\n");
+}
+
+#define FORMAT_X "rgb:%02hhX/%02hhX/%02hhX"
+
+static const char *Resources[SchemeLen] = {
+	[Background] = "background",
+	[Foreground] = "foreground",
+	[Bold] = "colorBD",
+	[Selection] = "highlightColor",
+	[Cursor] = "cursorColor",
+};
+
+static void outputXTerm(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		if (Resources[i]) {
+			printf("XTerm*%s: " FORMAT_X "\n", Resources[i], rgb.r, rgb.g, rgb.b);
+		} else {
+			printf("XTerm*color%u: " FORMAT_X "\n", i, rgb.r, rgb.g, rgb.b);
+		}
+	}
+}
+
+static const char *Mintty[SchemeLen] = {
+	"Black", "Red", "Green", "Yellow",
+	"Blue", "Magenta", "Cyan", "White",
+	"BoldBlack", "BoldRed", "BoldGreen", "BoldYellow",
+	"BoldBlue", "BoldMagenta", "BoldCyan", "BoldWhite",
+	[Background] = "BackgroundColour",
+	[Foreground] = "ForegroundColour",
+	[Cursor]     = "CursorColour",
+};
+
+static void outputMintty(const struct HSV *hsv, uint len) {
+	for (uint i = 0; i < len; ++i) {
+		if (!Mintty[i]) continue;
+		struct RGB rgb = convert(hsv[i]);
+		printf("%s=%hhu,%hhu,%hhu\n", Mintty[i], rgb.r, rgb.g, rgb.b);
+	}
+}
+
+static void outputCSS(const struct HSV *hsv, uint len) {
+	printf(":root {\n");
+	for (uint i = 0; i < len; ++i) {
+		struct RGB rgb = convert(hsv[i]);
+		printf("\t--ansi%u: #" FORMAT_RGB ";\n", i, rgb.r, rgb.g, rgb.b);
+	}
+	printf("}\n");
+	for (uint i = 0; i < len; ++i) {
+		printf(
+			".fg%u { color: var(--ansi%u); }\n"
+			".bg%u { background-color: var(--ansi%u); }\n",
+			i, i, i, i
+		);
+	}
+}
+
+enum {
+	SwatchWidth = 64,
+	SwatchHeight = 64,
+	SwatchCols = 8,
+};
+
+static void outputPNG(const struct HSV *hsv, uint len) {
+	uint rows = (len + SwatchCols - 1) / SwatchCols;
+	uint width = SwatchWidth * SwatchCols;
+	uint height = SwatchHeight * rows;
+	pngHead(stdout, width, height, 8, PNGIndexed);
+
+	struct RGB pal[len];
+	for (uint i = 0; i < len; ++i) {
+		pal[i] = convert(hsv[i]);
+	}
+	pngPalette(stdout, (byte *)pal, sizeof(pal));
+
+	byte data[height][1 + width];
+	memset(data, 0, sizeof(data));
+	for (uint y = 0; y < height; ++y) {
+		data[y][0] = (y % SwatchHeight ? PNGUp : PNGSub);
+	}
+	for (uint i = 0; i < len; ++i) {
+		uint y = SwatchHeight * (i / SwatchCols);
+		uint x = SwatchWidth * (i % SwatchCols);
+		data[y][1 + x] = (x ? 1 : i);
+	}
+	pngData(stdout, (byte *)data, sizeof(data));
+	pngTail(stdout);
+}
+
+int main(int argc, char *argv[]) {
+	generate();
+
+	OutputFn *output = outputRGB;
+	const struct HSV *hsv = scheme;
+	uint len = 16;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "Xacghilmp:stx"))) {
+		switch (opt) {
+			break; case 'X': output = outputXTerm;
+			break; case 'a': len = 16;
+			break; case 'c': output = outputEnum;
+			break; case 'g': output = outputPNG;
+			break; case 'h': output = outputHSV;
+			break; case 'i': invert();
+			break; case 'l': output = outputLinux;
+			break; case 'm': output = outputMintty;
+			break; case 'p': {
+				uint p = strtoul(optarg, NULL, 0);
+				if (p >= SchemeLen) return EX_USAGE;
+				hsv = &scheme[p];
+				len = 1;
+			}
+			break; case 's': output = outputCSS;
+			break; case 't': len = SchemeLen;
+			break; case 'x': output = outputRGB;
+			break; default:  return EX_USAGE;
+		}
+	}
+
+	output(hsv, len);
+}
diff --git a/bin/sh.l b/bin/sh.l
new file mode 100644
index 00000000..9fc241da
--- /dev/null
+++ b/bin/sh.l
@@ -0,0 +1,178 @@
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%option prefix="sh"
+%option noyywrap
+
+%{
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include "hilex.h"
+
+enum { Cap = 64 };
+static int len = 1;
+static int stack[Cap];
+static int push(int val) {
+	if (len < Cap) stack[len++] = val;
+	return val;
+}
+static int pop(void) {
+	if (len > 1) len--;
+	return stack[len-1];
+}
+%}
+
+%s Param Command Arith Backtick
+%x DQuote HereDocDel HereDoc HereDocLit
+
+word [[:alnum:]_.-]+
+param [^:=?+%#{}-]+
+reserved [!{}]|else|do|elif|for|done|fi|then|until|while|if|case|esac
+
+%%
+	static bool first;
+	static char *delimiter;
+
+[[:blank:]]+ { return Normal; }
+
+"\\". { return Escape; }
+
+<INITIAL,DQuote,HereDoc,Param,Command,Arith>{
+	"$"[*@#?$!0-9-] |
+	"$"[_[:alpha:][_[:alnum:]]* |
+	"${"[#]?{param}"}" {
+		return Subst;
+	}
+	"${"{param} {
+		BEGIN(push(Param));
+		return Subst;
+	}
+	"$(" {
+		BEGIN(push(Command));
+		return Subst;
+	}
+	"$((" {
+		BEGIN(push(Arith));
+		return Subst;
+	}
+	"`" {
+		BEGIN(push(Backtick));
+		return Subst;
+	}
+}
+<Param>"}" |
+<Command>")" |
+<Arith>"))" |
+<Backtick>"`" {
+	BEGIN(pop());
+	return Subst;
+}
+
+"\n" {
+	first = true;
+	return Normal;
+}
+[&();|]|"&&"|";;"|"||" {
+	first = true;
+	return Operator;
+}
+[0-9]?([<>]"&"?|">|"|">>"|"<>") {
+	return Operator;
+}
+
+{reserved} {
+	if (first) {
+		first = false;
+		return Keyword;
+	}
+	return Normal;
+}
+
+{word}/[[:blank:]]*"()" { return Ident; }
+
+[0-9]?("<<"|"<<-") {
+	BEGIN(push(HereDocDel));
+	return Operator;
+}
+<HereDocDel>{
+	[[:blank:]]+ { return Normal; }
+	{word} {
+		delimiter = strdup(yytext);
+		assert(delimiter);
+		BEGIN(pop(), push(HereDoc));
+		return Ident;
+	}
+	"'"{word}"'" {
+		delimiter = strndup(&yytext[1], strlen(yytext)-2);
+		assert(delimiter);
+		BEGIN(pop(), push(HereDocLit));
+		return Ident;
+	}
+}
+<HereDoc,HereDocLit>{
+	^"\t"*{word} {
+		if (strcmp(&yytext[strspn(yytext, "\t")], delimiter)) REJECT;
+		free(delimiter);
+		BEGIN(pop());
+		return Ident;
+	}
+}
+<HereDoc>{
+	[^$`\n]+ { return String; }
+	.|\n { return String; }
+}
+<HereDocLit>{
+	.*\n { return String; }
+}
+
+"'"[^'']*"'" { return String; }
+
+"\""/[^$`\\] {
+	BEGIN(push(DQuote));
+	yymore();
+}
+"\"" {
+	BEGIN(push(DQuote));
+	return String;
+}
+
+<DQuote>{
+	[^\\$`""]*"\"" {
+		BEGIN(pop());
+		return String;
+	}
+	"\\"[$`""\\\n] { return Escape; }
+	[^\\$`""]+|. { return String; }
+}
+
+<INITIAL,Command,Backtick,Arith>"#".* { return Comment; }
+
+{word} {
+	first = false;
+	return Normal;
+}
+
+.|\n { return Normal; }
+
+%{
+	(void)yyunput;
+	(void)input;
+%}
+
+%%
+
+const struct Lexer LexSh = { yylex, &yyin, &yytext };
diff --git a/bin/shotty.c b/bin/shotty.c
new file mode 100644
index 00000000..de7fc8ac
--- /dev/null
+++ b/bin/shotty.c
@@ -0,0 +1,648 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <err.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#define BIT(x) x##Bit, x = 1 << x##Bit, x##Bit_ = x##Bit
+
+typedef unsigned uint;
+
+enum {
+	NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL,
+	BS, HT, NL, VT, NP, CR, SO, SI,
+	DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB,
+	CAN, EM, SUB, ESC, FS, GS, RS, US,
+	DEL = 0x7F,
+};
+
+enum Attr {
+	BIT(Bold),
+	BIT(Dim),
+	BIT(Italic),
+	BIT(Underline),
+	BIT(Blink),
+	BIT(Reverse),
+};
+
+struct Style {
+	enum Attr attr;
+	int bg, fg;
+};
+
+struct Cell {
+	struct Style style;
+	wchar_t ch;
+};
+
+static uint rows = 24, cols = 80;
+static struct Cell *cells;
+
+static struct Cell *cell(uint y, uint x) {
+	assert(y <= rows);
+	assert(x <= cols);
+	assert(y * cols + x <= rows * cols);
+	return &cells[y * cols + x];
+}
+
+static uint y, x;
+static struct Style style = { .bg = -1, .fg = -1 };
+
+static struct {
+	uint y, x;
+} save;
+
+enum { ParamCap = 16 };
+static struct {
+	uint s[ParamCap];
+	uint n, i;
+} param;
+
+static uint p(uint i, uint z) {
+	return (i < param.n ? param.s[i] : z);
+}
+
+static uint min(uint a, uint b) {
+	return (a < b ? a : b);
+}
+
+#define _ch ch __attribute__((unused))
+typedef void Action(wchar_t ch);
+
+static void nop(wchar_t _ch) {
+}
+
+static void csi(wchar_t _ch) {
+	memset(&param, 0, sizeof(param));
+}
+
+static void csiSep(wchar_t _ch) {
+	if (param.n == ParamCap) return;
+	if (!param.n) param.n++;
+	param.n++;
+	param.i++;
+}
+
+static void csiDigit(wchar_t ch) {
+	param.s[param.i] *= 10;
+	param.s[param.i] += ch - L'0';
+	if (!param.n) param.n++;
+}
+
+static void bs(wchar_t _ch)  { if (x) x--; }
+static void ht(wchar_t _ch)  { x = min(x - x % 8 + 8, cols - 1); }
+static void cr(wchar_t _ch)  { x = 0; }
+static void cuu(wchar_t _ch) { y -= min(p(0, 1), y); }
+static void cud(wchar_t _ch) { y  = min(y + p(0, 1), rows - 1); }
+static void cuf(wchar_t _ch) { x  = min(x + p(0, 1), cols - 1); }
+static void cub(wchar_t _ch) { x -= min(p(0, 1), x); }
+static void cnl(wchar_t _ch) { x = 0; cud(0); }
+static void cpl(wchar_t _ch) { x = 0; cuu(0); }
+static void cha(wchar_t _ch) { x = min(p(0, 1) - 1, cols - 1); }
+static void vpa(wchar_t _ch) { y = min(p(0, 1) - 1, rows - 1); }
+static void cup(wchar_t _ch) {
+	y = min(p(0, 1) - 1, rows - 1);
+	x = min(p(1, 1) - 1, cols - 1);
+}
+static void decsc(wchar_t _ch) {
+	save.y = y;
+	save.x = x;
+}
+static void decrc(wchar_t _ch) {
+	y = save.y;
+	x = save.x;
+}
+
+static void move(struct Cell *dst, struct Cell *src, size_t len) {
+	memmove(dst, src, sizeof(*dst) * len);
+}
+
+static void erase(struct Cell *at, struct Cell *to) {
+	for (; at < to; ++at) {
+		at->style = style;
+		at->ch = L' ';
+	}
+}
+
+static void ed(wchar_t _ch) {
+	erase(
+		(p(0, 0) == 0 ? cell(y, x) : cell(0, 0)),
+		(p(0, 0) == 1 ? cell(y, x) : cell(rows - 1, cols))
+	);
+}
+static void el(wchar_t _ch) {
+	erase(
+		(p(0, 0) == 0 ? cell(y, x) : cell(y, 0)),
+		(p(0, 0) == 1 ? cell(y, x) : cell(y, cols))
+	);
+}
+static void ech(wchar_t _ch) {
+	erase(cell(y, x), cell(y, min(x + p(0, 1), cols)));
+}
+
+static void dch(wchar_t _ch) {
+	uint n = min(p(0, 1), cols - x);
+	move(cell(y, x), cell(y, x + n), cols - x - n);
+	erase(cell(y, cols - n), cell(y, cols));
+}
+static void ich(wchar_t _ch) {
+	uint n = min(p(0, 1), cols - x);
+	move(cell(y, x + n), cell(y, x), cols - x - n);
+	erase(cell(y, x), cell(y, x + n));
+}
+
+static struct {
+	uint top, bot;
+} scroll;
+
+static void scrollUp(uint top, uint n) {
+	n = min(n, scroll.bot - top);
+	move(cell(top, 0), cell(top + n, 0), cols * (scroll.bot - top - n));
+	erase(cell(scroll.bot - n, 0), cell(scroll.bot, 0));
+}
+
+static void scrollDown(uint top, uint n) {
+	n = min(n, scroll.bot - top);
+	move(cell(top + n, 0), cell(top, 0), cols * (scroll.bot - top - n));
+	erase(cell(top, 0), cell(top + n, 0));
+}
+
+static void decstbm(wchar_t _ch) {
+	scroll.bot = min(p(1, rows), rows);
+	scroll.top = min(p(0, 1) - 1, scroll.bot);
+}
+
+static void su(wchar_t _ch) { scrollUp(scroll.top, p(0, 1)); }
+static void sd(wchar_t _ch) { scrollDown(scroll.top, p(0, 1)); }
+static void dl(wchar_t _ch) { scrollUp(min(y, scroll.bot), p(0, 1)); }
+static void il(wchar_t _ch) { scrollDown(min(y, scroll.bot), p(0, 1)); }
+
+static void nl(wchar_t _ch) {
+	if (y + 1 == scroll.bot) {
+		scrollUp(scroll.top, 1);
+	} else {
+		y = min(y + 1, rows - 1);
+	}
+}
+static void ri(wchar_t _ch) {
+	if (y == scroll.top) {
+		scrollDown(scroll.top, 1);
+	} else {
+		if (y) y--;
+	}
+}
+
+static enum Mode {
+	BIT(Insert),
+	BIT(Wrap),
+	BIT(Cursor),
+} mode = Wrap | Cursor;
+
+static enum Mode paramMode(void) {
+	enum Mode mode = 0;
+	for (uint i = 0; i < param.n; ++i) {
+		switch (param.s[i]) {
+			break; case 4: mode |= Insert;
+			break; default: warnx("unhandled SM/RM %u", param.s[i]);
+		}
+	}
+	return mode;
+}
+
+static enum Mode paramDECMode(void) {
+	enum Mode mode = 0;
+	for (uint i = 0; i < param.n; ++i) {
+		switch (param.s[i]) {
+			break; case 1: // DECCKM
+			break; case 7: mode |= Wrap;
+			break; case 12: // "Start Blinking Cursor"
+			break; case 25: mode |= Cursor;
+			break; default: {
+				if (param.s[i] < 1000) {
+					warnx("unhandled DECSET/DECRST %u", param.s[i]);
+				}
+			}
+		}
+	}
+	return mode;
+}
+
+static void sm(wchar_t _ch) { mode |= paramMode(); }
+static void rm(wchar_t _ch) { mode &= ~paramMode(); }
+static void decset(wchar_t _ch) { mode |= paramDECMode(); }
+static void decrst(wchar_t _ch) { mode &= ~paramDECMode(); }
+
+enum {
+	Reset,
+	SetBold,
+	SetDim,
+	SetItalic,
+	SetUnderline,
+	SetBlink,
+	SetReverse = 7,
+
+	UnsetBoldDim = 22,
+	UnsetItalic,
+	UnsetUnderline,
+	UnsetBlink,
+	UnsetReverse = 27,
+
+	SetFg0 = 30,
+	SetFg7 = 37,
+	SetFg,
+	ResetFg,
+	SetBg0 = 40,
+	SetBg7 = 47,
+	SetBg,
+	ResetBg,
+
+	SetFg8 = 90,
+	SetFgF = 97,
+	SetBg8 = 100,
+	SetBgF = 107,
+
+	Color256 = 5,
+};
+
+static void sgr(wchar_t _ch) {
+	uint n = param.i + 1;
+	for (uint i = 0; i < n; ++i) {
+		switch (param.s[i]) {
+			break; case Reset: style = (struct Style) { .bg = -1, .fg = -1 };
+
+			break; case SetBold:      style.attr |= Bold; style.attr &= ~Dim;
+			break; case SetDim:       style.attr |= Dim; style.attr &= ~Bold;
+			break; case SetItalic:    style.attr |= Italic;
+			break; case SetUnderline: style.attr |= Underline;
+			break; case SetBlink:     style.attr |= Blink;
+			break; case SetReverse:   style.attr |= Reverse;
+
+			break; case UnsetBoldDim:   style.attr &= ~(Bold | Dim);
+			break; case UnsetItalic:    style.attr &= ~Italic;
+			break; case UnsetUnderline: style.attr &= ~Underline;
+			break; case UnsetBlink:     style.attr &= ~Blink;
+			break; case UnsetReverse:   style.attr &= ~Reverse;
+
+			break; case SetFg: {
+				if (++i < n && param.s[i] == Color256) {
+					if (++i < n) style.fg = param.s[i];
+				}
+			}
+			break; case SetBg: {
+				if (++i < n && param.s[i] == Color256) {
+					if (++i < n) style.bg = param.s[i];
+				}
+			}
+
+			break; case ResetFg: style.fg = -1;
+			break; case ResetBg: style.bg = -1;
+
+			break; default: {
+				uint p = param.s[i];
+				if (p >= SetFg0 && p <= SetFg7) {
+					style.fg = p - SetFg0;
+				} else if (p >= SetBg0 && p <= SetBg7) {
+					style.bg = p - SetBg0;
+				} else if (p >= SetFg8 && p <= SetFgF) {
+					style.fg = 8 + p - SetFg8;
+				} else if (p >= SetBg8 && p <= SetBgF) {
+					style.bg = 8 + p - SetBg8;
+				} else {
+					warnx("unhandled SGR %u", p);
+				}
+			}
+		}
+	}
+}
+
+static enum {
+	USASCII,
+	DECSpecial,
+} charset;
+
+static void usascii(wchar_t _ch) { charset = USASCII; }
+static void decSpecial(wchar_t _ch) { charset = DECSpecial; }
+
+static const wchar_t AltCharset[128] = {
+	['`'] = L'â—†', ['a'] = L'â–’', ['f'] = L'°', ['g'] = L'±', ['i'] = L'â‹',
+	['j'] = L'┘', ['k'] = L'â”', ['l'] = L'┌', ['m'] = L'â””', ['n'] = L'┼',
+	['o'] = L'⎺', ['p'] = L'⎻', ['q'] = L'─', ['r'] = L'⎼', ['s'] = L'⎽',
+	['t'] = L'├', ['u'] = L'┤', ['v'] = L'┴', ['w'] = L'┬', ['x'] = L'│',
+	['y'] = L'≤', ['z'] = L'≥', ['{'] = L'π', ['|'] = L'≠', ['}'] = L'£',
+	['~'] = L'·',
+};
+
+static void add(wchar_t ch) {
+	if (charset == DECSpecial && ch < 128 && AltCharset[ch]) {
+		ch = AltCharset[ch];
+	}
+
+	int width = wcwidth(ch);
+	if (width < 0) {
+		warnx("unhandled \\u%02X", ch);
+		return;
+	}
+
+	if (mode & Insert) {
+		uint n = min(width, cols - x);
+		move(cell(y, x + n), cell(y, x), cols - x - n);
+	}
+	if (mode & Wrap && x + width > cols) {
+		cr(0);
+		nl(0);
+	}
+
+	cell(y, x)->style = style;
+	cell(y, x)->ch = ch;
+	for (int i = 1; i < width && x + i < cols; ++i) {
+		cell(y, x + i)->style = style;
+		cell(y, x + i)->ch = L'\0';
+	}
+	x = min(x + width, (mode & Wrap ? cols : cols - 1));
+}
+
+static void html(void);
+static void mc(wchar_t _ch) {
+	if (p(0, 0) == 10) {
+		html();
+	} else {
+		warnx("unhandled CSI %u MC", p(0, 0));
+	}
+}
+
+static enum {
+	Data,
+	Esc,
+	G0,
+	CSI,
+	CSILt,
+	CSIEq,
+	CSIGt,
+	CSIQm,
+	CSIInter,
+	OSC,
+	OSCEsc,
+} state;
+
+static void escDefault(wchar_t ch) {
+	warnx("unhandled ESC %lc", ch);
+}
+
+static void g0Default(wchar_t ch) {
+	warnx("unhandled G0 %lc", ch);
+	charset = USASCII;
+}
+
+static void csiInter(wchar_t ch) {
+	switch (state) {
+		break; case CSI: warnx("unhandled CSI %lc ...", ch);
+		break; case CSILt: warnx("unhandled CSI < %lc ...", ch);
+		break; case CSIEq: warnx("unhandled CSI = %lc ...", ch);
+		break; case CSIGt: warnx("unhandled CSI > %lc ...", ch);
+		break; case CSIQm: warnx("unhandled CSI ? %lc ...", ch);
+		break; default: abort();
+	}
+}
+
+static void csiFinal(wchar_t ch) {
+	switch (state) {
+		break; case CSI: warnx("unhandled CSI %lc", ch);
+		break; case CSILt: warnx("unhandled CSI < %lc", ch);
+		break; case CSIEq: warnx("unhandled CSI = %lc", ch);
+		break; case CSIGt: warnx("unhandled CSI > %lc", ch);
+		break; case CSIQm: warnx("unhandled CSI ? %lc", ch);
+		break; case CSIInter: warnx("unhandled CSI ... %lc", ch);
+		break; default: abort();
+	}
+}
+
+#define S(s) break; case s: switch (ch)
+#define A(c, a, s) break; case c: a(ch); state = s
+#define D(a, s) break; default: a(ch); state = s
+static void update(wchar_t ch) {
+	switch (state) {
+		default: abort();
+
+		S(Data) {
+			A(BEL, nop, Data);
+			A(BS,  bs,  Data);
+			A(HT,  ht,  Data);
+			A(NL,  nl,  Data);
+			A(CR,  cr,  Data);
+			A(ESC, nop, Esc);
+			D(add, Data);
+		}
+
+		S(Esc) {
+			A('(', nop, G0);
+			A('7', decsc, Data);
+			A('8', decrc, Data);
+			A('=', nop, Data);
+			A('>', nop, Data);
+			A('M', ri,  Data);
+			A('[', csi, CSI);
+			A(']', nop, OSC);
+			D(escDefault, Data);
+		}
+		S(G0) {
+			A('0', decSpecial, Data);
+			A('B', usascii, Data);
+			D(g0Default, Data);
+		}
+
+		S(CSI) {
+			A(' ' ... '/', csiInter, CSIInter);
+			A('0' ... '9', csiDigit, CSI);
+			A(':', nop, CSI);
+			A(';', csiSep, CSI);
+			A('<', nop, CSILt);
+			A('=', nop, CSIEq);
+			A('>', nop, CSIGt);
+			A('?', nop, CSIQm);
+			A('@', ich, Data);
+			A('A', cuu, Data);
+			A('B', cud, Data);
+			A('C', cuf, Data);
+			A('D', cub, Data);
+			A('E', cnl, Data);
+			A('F', cpl, Data);
+			A('G', cha, Data);
+			A('H', cup, Data);
+			A('J', ed,  Data);
+			A('K', el,  Data);
+			A('L', il,  Data);
+			A('M', dl,  Data);
+			A('P', dch, Data);
+			A('S', su,  Data);
+			A('T', sd,  Data);
+			A('X', ech, Data);
+			A('d', vpa, Data);
+			A('h', sm,  Data);
+			A('i', mc,  Data);
+			A('l', rm,  Data);
+			A('m', sgr, Data);
+			A('r', decstbm, Data);
+			A('t', nop, Data);
+			D(csiFinal, Data);
+		}
+
+		S(CSILt ... CSIGt) {
+			A(' ' ... '/', csiInter, CSIInter);
+			A('0' ... '9', csiDigit, state);
+			A(':', nop, state);
+			A(';', csiSep, state);
+			D(csiFinal, Data);
+		}
+
+		S(CSIQm) {
+			A(' ' ... '/', csiInter, CSIInter);
+			A('0' ... '9', csiDigit, CSIQm);
+			A(':', nop, CSIQm);
+			A(';', csiSep, CSIQm);
+			A('h', decset, Data);
+			A('l', decrst, Data);
+			D(csiFinal, Data);
+		}
+
+		S(CSIInter) {
+			D(csiFinal, Data);
+		}
+
+		S(OSC) {
+			A(BEL, nop, Data);
+			A(ESC, nop, OSCEsc);
+			D(nop, OSC);
+		}
+		S(OSCEsc) {
+			A('\\', nop, Data);
+			D(nop, OSC);
+		}
+	}
+}
+
+static bool bright;
+static int defaultBg = 0;
+static int defaultFg = 7;
+
+static void span(const struct Style *prev, const struct Cell *cell) {
+	struct Style style = cell->style;
+	if (!prev || memcmp(prev, &style, sizeof(*prev))) {
+		if (prev) printf("</span>");
+		if (style.bg < 0) style.bg = defaultBg;
+		if (style.fg < 0) style.fg = defaultFg;
+		if (bright && style.attr & Bold) {
+			if (style.fg < 8) style.fg += 8;
+			style.attr ^= Bold;
+		}
+		printf(
+			"<span style=\"%s%s%s\" class=\"bg%u fg%u\">",
+			(style.attr & Bold ? "font-weight:bold;" : ""),
+			(style.attr & Italic ? "font-style:italic;" : ""),
+			(style.attr & Underline ? "text-decoration:underline;" : ""),
+			(style.attr & Reverse ? style.fg : style.bg),
+			(style.attr & Reverse ? style.bg : style.fg)
+		);
+	}
+	switch (cell->ch) {
+		break; case '&': printf("&amp;");
+		break; case '<': printf("&lt;");
+		break; case '>': printf("&gt;");
+		break; default:  printf("%lc", (wint_t)cell->ch);
+	}
+}
+
+static bool mediaCopy;
+static void html(void) {
+	mediaCopy = true;
+	if (mode & Cursor) cell(y, x)->style.attr ^= Reverse;
+	printf(
+		"<pre style=\"width: %uch;\" class=\"bg%u fg%u\">",
+		cols, defaultBg, defaultFg
+	);
+	for (uint y = 0; y < rows; ++y) {
+		for (uint x = 0; x < cols; ++x) {
+			if (!cell(y, x)->ch) continue;
+			span(x ? &cell(y, x - 1)->style : NULL, cell(y, x));
+		}
+		printf("</span>\n");
+	}
+	printf("</pre>\n");
+	if (mode & Cursor) cell(y, x)->style.attr ^= Reverse;
+}
+
+int main(int argc, char *argv[]) {
+	setlocale(LC_CTYPE, "");
+
+	bool debug = false;
+	bool size = false;
+	bool hide = false;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "Bb:df:h:nsw:"))) {
+		switch (opt) {
+			break; case 'B': bright = true;
+			break; case 'b': defaultBg = strtol(optarg, NULL, 0);
+			break; case 'd': debug = true;
+			break; case 'f': defaultFg = strtol(optarg, NULL, 0);
+			break; case 'h': rows = strtoul(optarg, NULL, 0);
+			break; case 'n': hide = true;
+			break; case 's': size = true;
+			break; case 'w': cols = strtoul(optarg, NULL, 0);
+			break; default:  return EX_USAGE;
+		}
+	}
+
+	FILE *file = stdin;
+	if (optind < argc) {
+		file = fopen(argv[optind], "r");
+		if (!file) err(EX_NOINPUT, "%s", argv[optind]);
+	}
+
+	if (size) {
+		struct winsize window;
+		int error = ioctl(STDERR_FILENO, TIOCGWINSZ, &window);
+		if (error) err(EX_IOERR, "ioctl");
+		rows = window.ws_row;
+		cols = window.ws_col;
+	}
+	scroll.bot = rows;
+
+	cells = calloc(rows * cols, sizeof(*cells));
+	if (!cells) err(EX_OSERR, "calloc");
+	erase(cell(0, 0), cell(rows - 1, cols));
+
+	wint_t ch;
+	while (WEOF != (ch = getwc(file))) {
+		uint prev = state;
+		update(ch);
+		if (debug && state != prev && state == Data) html();
+	}
+	if (ferror(file)) err(EX_IOERR, "getwc");
+
+	if (!mediaCopy) {
+		if (hide) mode &= ~Cursor;
+		html();
+	}
+}
diff --git a/bin/sup.sh b/bin/sup.sh
new file mode 100644
index 00000000..b7f28bc7
--- /dev/null
+++ b/bin/sup.sh
@@ -0,0 +1,169 @@
+#!/bin/sh
+set -eu
+
+service=$1
+email=${2:-$(git config fetchemail.imapUser)}
+
+generate() {
+	openssl rand -base64 33
+}
+copy() {
+	printf '%s' "$1" | pbcopy
+}
+
+asciinema() {
+	echo 'Fetching CSRF token...'
+	jar=$(mktemp -t sup)
+	trap 'rm "${jar}"' EXIT
+	csrf=$(
+		curl -Ss -c "${jar}" 'https://asciinema.org/login/new' |
+		sed -n 's/.*name="_csrf_token".*value="\([^"]*\)".*/\1/p'
+	)
+	echo 'Submitting form...'
+	curl -Ss -X POST -b "${jar}" \
+		-F "_csrf_token=${csrf}" -F "login[email]=${email}" \
+		'https://asciinema.org/login' \
+		>/dev/null
+	echo 'Waiting for email...'
+	url=$(
+		git fetch-email -i -M Trash \
+			-F 'hello@asciinema.org' -T "${email}" \
+			-S 'Login to asciinema.org' |
+		grep -m 1 '^https://asciinema\.org/session/new'
+	)
+	open "${url}"
+}
+
+bugzilla() {
+	echo 'Fetching CSRF token...'
+	csrf=$(
+		curl -Ss "${bugzillaBase}/" |
+		sed -n '
+			/name="token"/N
+			s/.*name="token"[[:space:]]*value="\([^"]*\)".*/\1/p
+		' | head -n 1
+	)
+	echo 'Submitting form...'
+	curl -Ss -X POST \
+		-F "loginname=${email}" -F "token=${csrf}" -F 'a=reqpw' \
+		"${bugzillaBase}/token.cgi" \
+		>/dev/null
+	echo 'Waiting for email...'
+	token=$(
+		git fetch-email -i -M Trash \
+			-F "${bugzillaFrom}" -T "${email}" \
+			-S 'Bugzilla Change Password Request' |
+		sed -n 's/.*t=3D\([^&]*\).*/\1/p' |
+		head -n 1
+	)
+	password=$(generate)
+	echo 'Setting password...'
+	curl -Ss -X POST \
+		-F "t=${token}" -F 'a=chgpw' \
+		-F "password=${password}" -F "matchpassword=${password}" \
+		"${bugzillaBase}/token.cgi" \
+		>/dev/null
+	copy "${password}"
+	open "${bugzillaBase}/"
+}
+
+freebsdbugzilla() {
+	bugzillaBase='https://bugs.freebsd.org/bugzilla'
+	bugzillaFrom='bugzilla-noreply@freebsd.org'
+	bugzilla
+}
+
+discogs() {
+	echo 'Submitting form...'
+	curl -Ss -X POST \
+		-F "email=${email}" -F 'Action.EmailResetInstructions=submit' \
+		'https://www.discogs.com/users/forgot_password' \
+		>/dev/null
+	echo 'Waiting for email...'
+	url=$(
+		git fetch-email -i -M Trash \
+			-F 'noreply@discogs.com' -T "${email}" \
+			-S 'Discogs Account Password Reset Instructions' |
+		sed -n 's/^To proceed, follow the instructions here: \(.*\)/\1/p'
+	)
+	echo 'Fetching token...'
+	token=$(curl -ISs --url "${url}" | sed -n 's/.*[?]token=\([^&]*\).*/\1/p')
+	password=$(generate)
+	echo 'Setting password...'
+	curl -Ss -X POST \
+		-F "token=${token}" \
+		-F "password0=${password}" -F "password1=${password}" \
+		-F 'Action.ChangePassword=submit' \
+		'https://www.discogs.com/users/forgot_password' \
+		>/dev/null
+	copy "${password}"
+	open 'https://discogs.com/login'
+}
+
+liberapay() {
+	echo 'Fetching CSRF token...'
+	csrf=$(
+		curl -Ss 'https://liberapay.com/sign-in' |
+		sed -n 's/.*name="csrf_token".*value="\([^"]*\)".*/\1/p'
+	)
+	echo 'Submitting form...'
+	curl -Ss -X POST \
+		-b "csrf_token=${csrf}" -F "csrf_token=${csrf}" \
+		-F "log-in.id=${email}" \
+		'https://liberapay.com/sign-in' \
+		>/dev/null
+	echo 'Waiting for email...'
+	url=$(
+		git fetch-email -i -M Trash \
+			-F 'support@liberapay.com' -T "${email}" \
+			-S 'Log in to Liberapay' |
+		grep -m 1 '^https://liberapay\.com/'
+	)
+	open "${url}"
+}
+
+lobsters() {
+	: ${lobstersBase:=https://lobste.rs}
+	: ${lobstersFrom:=nobody@lobste.rs}
+	echo 'Fetching CSRF token...'
+	csrf=$(
+		curl -Ss "${lobstersBase}/login/forgot_password" |
+		sed -n 's/.*name="authenticity_token" value="\([^"]*\)".*/\1/p'
+	)
+	echo 'Submitting form...'
+	curl -Ss -X POST \
+		-F "authenticity_token=${csrf}" \
+		-F "email=${email}" -F 'commit=submit' \
+		"${lobstersBase}/login/reset_password" \
+		>/dev/null
+	echo 'Waiting for email...'
+	token=$(
+		git fetch-email -i -M Trash \
+			-F "${lobstersFrom}" -T "${email}" \
+			-S 'Reset your password' |
+		sed -n 's|^https://.*[?]token=\(.*\)|\1|p'
+	)
+	echo 'Fetching CSRF token...'
+	csrf=$(
+		curl -Ss "${lobstersBase}/login/set_new_password?token=${token}" |
+		sed -n 's/.*name="authenticity_token" value="\([^"]*\)".*/\1/p'
+	)
+	password=$(generate)
+	echo 'Setting password...'
+	curl -Ss -X POST \
+		-F "authenticity_token=${csrf}" -F "token=${token}" \
+		-F "password=${password}" -F "password_confirmation=${password}" \
+		-F 'commit=submit' \
+		"${lobstersBase}/login/set_new_password" \
+		>/dev/null
+	copy "${password}"
+	open "${lobstersBase}/login"
+}
+
+tildenews() {
+	lobstersBase='https://tilde.news'
+	lobstersFrom='nobody@tilde.news'
+	lobsters
+}
+
+$service
diff --git a/bin/title.c b/bin/title.c
new file mode 100644
index 00000000..47ff720a
--- /dev/null
+++ b/bin/title.c
@@ -0,0 +1,211 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <curl/curl.h>
+#include <err.h>
+#include <locale.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <wchar.h>
+
+static regex_t regex(const char *pattern, int flags) {
+	regex_t regex;
+	int error = regcomp(&regex, pattern, REG_EXTENDED | flags);
+	if (!error) return regex;
+
+	char buf[256];
+	regerror(error, &regex, buf, sizeof(buf));
+	errx(EX_SOFTWARE, "regcomp: %s: %s", buf, pattern);
+}
+
+static const struct Entity {
+	wchar_t ch;
+	const char *name;
+} Entities[] = {
+	{ L'"', "&quot;" },
+	{ L'&', "&amp;" },
+	{ L'<', "&lt;" },
+	{ L'>', "&gt;" },
+	{ L'â¤', "&#10;" },
+};
+
+static wchar_t entity(const char *name) {
+	for (size_t i = 0; i < sizeof(Entities) / sizeof(Entities[0]); ++i) {
+		struct Entity entity = Entities[i];
+		if (strncmp(name, entity.name, strlen(entity.name))) continue;
+		return entity.ch;
+	}
+	if (!strncmp(name, "&#x", 3)) return strtoul(&name[3], NULL, 16);
+	if (!strncmp(name, "&#", 2)) return strtoul(&name[2], NULL, 10);
+	return 0;
+}
+
+static const char EntityPattern[] = {
+	"[[:space:]]+|&([[:alpha:]]+|#([[:digit:]]+|x[[:xdigit:]]+));"
+};
+static regex_t EntityRegex;
+
+static void showTitle(const char *title) {
+	regmatch_t match = {0};
+	for (; *title; title += match.rm_eo) {
+		if (regexec(&EntityRegex, title, 1, &match, 0)) break;
+		if (title[match.rm_so] != '&') {
+			printf("%.*s ", (int)match.rm_so, title);
+			continue;
+		}
+		wchar_t ch = entity(&title[match.rm_so]);
+		if (ch) {
+			printf("%.*s%lc", (int)match.rm_so, title, (wint_t)ch);
+		} else {
+			printf("%.*s", (int)match.rm_eo, title);
+		}
+	}
+	printf("%s\n", title);
+}
+
+static CURL *curl;
+static bool title;
+static struct {
+	char buf[64 * 1024];
+	size_t len;
+} body;
+
+// HE COMES
+static const char TitlePattern[] = "<title>([^<]*)</title>";
+static regex_t TitleRegex;
+
+static size_t handleBody(char *buf, size_t size, size_t nitems, void *user) {
+	(void)user;
+	size_t len = size * nitems;
+	size_t cap = sizeof(body.buf) - body.len - 1;
+	size_t new = (len < cap ? len : cap);
+	if (title || !new) return len;
+
+	memcpy(&body.buf[body.len], buf, new);
+	body.len += new;
+	body.buf[body.len] = '\0';
+
+	regmatch_t match[2];
+	if (regexec(&TitleRegex, body.buf, 2, match, 0)) return len;
+	body.buf[match[1].rm_eo] = '\0';
+	showTitle(&body.buf[match[1].rm_so]);
+	title = true;
+
+	return len;
+}
+
+static CURLcode fetchTitle(const char *url) {
+	CURLcode code = curl_easy_setopt(curl, CURLOPT_URL, url);
+	if (code) return code;
+
+	curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);
+	code = curl_easy_perform(curl);
+	if (code) return code;
+
+	char *type;
+	code = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &type);
+	if (code) return code;
+	if (!type || strncmp(type, "text/html", 9)) return CURLE_OK;
+
+	char *dest;
+	curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &dest);
+	dest = strdup(dest);
+	if (!dest) err(EX_OSERR, "strdup");
+
+	code = curl_easy_setopt(curl, CURLOPT_URL, dest);
+	if (code) return code;
+	free(dest);
+
+	body.len = 0;
+	title = false;
+	curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
+	code = curl_easy_perform(curl);
+	return code;
+}
+
+int main(int argc, char *argv[]) {
+	EntityRegex = regex(EntityPattern, 0);
+	TitleRegex = regex(TitlePattern, REG_ICASE);
+
+	setlocale(LC_CTYPE, "");
+	setlinebuf(stdout);
+
+	CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
+	if (code) errx(EX_OSERR, "curl_global_init: %s", curl_easy_strerror(code));
+
+	curl = curl_easy_init();
+	if (!curl) errx(EX_SOFTWARE, "curl_easy_init");
+
+	static char error[CURL_ERROR_SIZE];
+	curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error);
+
+	curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
+	curl_easy_setopt(
+		curl, CURLOPT_USERAGENT,
+		"curl/7.54.0 facebookexternalhit/1.1 Twitterbot/1.0"
+	);
+	curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "");
+	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+	curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3L);
+	curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
+
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handleBody);
+
+	bool exclude = false;
+	regex_t excludeRegex;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "x:v"))) {
+		switch (opt) {
+			break; case 'x': {
+				exclude = true;
+				excludeRegex = regex(optarg, REG_NOSUB);
+			}
+			break; case 'v': curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
+			break; default:  return EX_USAGE;
+		}
+	}
+
+	if (optind < argc) {
+		code = fetchTitle(argv[optind]);
+		if (!code) return EX_OK;
+		errx(EX_DATAERR, "curl_easy_perform: %s", error);
+	}
+
+	char *buf = NULL;
+	size_t cap = 0;
+
+	regex_t urlRegex = regex("https?://([^[:space:]>\"()]|[(][^)]*[)])+", 0);
+	while (0 < getline(&buf, &cap, stdin)) {
+		regmatch_t match = {0};
+		for (char *ptr = buf; *ptr; ptr += match.rm_eo) {
+			if (regexec(&urlRegex, ptr, 1, &match, 0)) break;
+			ptr[match.rm_eo] = '\0';
+			const char *url = &ptr[match.rm_so];
+			if (!exclude || regexec(&excludeRegex, url, 0, NULL, 0)) {
+				code = fetchTitle(url);
+				if (code) warnx("curl_easy_perform: %s", error);
+			}
+			ptr[match.rm_eo] = ' ';
+		}
+	}
+	if (ferror(stdin)) err(EX_IOERR, "getline");
+}
diff --git a/bin/typer.c b/bin/typer.c
new file mode 100644
index 00000000..186f8214
--- /dev/null
+++ b/bin/typer.c
@@ -0,0 +1,197 @@
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify this Program, or any covered work, by linking or
+ * combining it with LibreSSL (or a modified version of that library),
+ * containing parts covered by the terms of the OpenSSL License and the
+ * original SSLeay license, the licensors of this Program grant you
+ * additional permission to convey the resulting work. Corresponding
+ * Source for a non-source form of such a combination shall include the
+ * source code for the parts of LibreSSL used as well as that of the
+ * covered work.
+ */
+
+#include <err.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sysexits.h>
+#include <tls.h>
+#include <unistd.h>
+
+static bool verbose;
+static struct tls *client;
+static const char *chan;
+
+static void clientWrite(const char *ptr, size_t len) {
+	if (verbose) printf("%.*s", (int)len, ptr);
+	while (len) {
+		ssize_t ret = tls_write(client, ptr, len);
+		if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue;
+		if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client));
+		ptr += ret;
+		len -= ret;
+	}
+}
+
+static void format(const char *format, ...) {
+	char buf[1024];
+	va_list ap;
+	va_start(ap, format);
+	int len = vsnprintf(buf, sizeof(buf), format, ap);
+	va_end(ap);
+	if ((size_t)len > sizeof(buf) - 1) errx(EX_DATAERR, "message too large");
+	clientWrite(buf, len);
+}
+
+static bool joined;
+static bool reverse;
+static bool copy;
+
+static void handle(char *line) {
+	char *tags = NULL;
+	char *origin = NULL;
+	if (line && line[0] == '@') tags = 1 + strsep(&line, " ");
+	if (line && line[0] == ':') origin = 1 + strsep(&line, " ");
+	char *cmd = strsep(&line, " ");
+	if (!cmd) return;
+	if (!strcmp(cmd, "CAP")) {
+		char *param = strsep(&cmd, " ");
+		if (!param) errx(EX_PROTOCOL, "CAP missing parameter");
+		if (!strcmp(param, "NAK")) {
+			errx(EX_CONFIG, "server does not support message-tags");
+		}
+		format("CAP END\r\n");
+	} else if (!strcmp(cmd, "001")) {
+		format("JOIN %s\r\n", chan);
+		joined = true;
+	} else if (!strcmp(cmd, "PING")) {
+		format("PONG %s\r\n", line);
+	} else if (copy && !strcmp(cmd, "TAGMSG") && tags) {
+		if (strstr(tags, "typing=")) {
+			format("@%s TAGMSG %s\r\n", tags, chan);
+		}
+	} else if (reverse && !strcmp(cmd, "TAGMSG") && tags && origin) {
+		char *nick = strsep(&origin, "!");
+		if (strstr(tags, "typing=active")) {
+			format("PRIVMSG %s :\u2328\uFE0F %s is typing!\r\n", chan, nick);
+		} else if (strstr(tags, "typing=paused")) {
+			format("PRIVMSG %s :\U0001F914 %s is thinking!\r\n", chan, nick);
+		} else if (strstr(tags, "typing=done")) {
+			format("PRIVMSG %s :\u270B %s stopped typing!\r\n", chan, nick);
+		}
+	}
+}
+
+static void timer(int sig) {
+	(void)sig;
+	if (!joined) return;
+	const char *status = (arc4random_uniform(4) ? "active" : "done");
+	format(
+		"@+typing=%s;+draft/typing=%s TAGMSG %s\r\n",
+		status, status, chan
+	);
+}
+
+int main(int argc, char *argv[]) {
+	const char *host = NULL;
+	const char *port = "6697";
+	const char *cert = NULL;
+	const char *nick = "typer";
+	const char *user = "typer";
+	bool passive = false;
+
+	for (int opt; 0 < (opt = getopt(argc, argv, "CPRc:n:p:u:v"));) {
+		switch (opt) {
+			break; case 'C': copy = true;
+			break; case 'P': passive = true;
+			break; case 'R': reverse = true;
+			break; case 'c': cert = optarg;
+			break; case 'n': nick = optarg;
+			break; case 'p': port = optarg;
+			break; case 'u': user = optarg;
+			break; case 'v': verbose = true;
+			break; default:  return EX_USAGE;
+		}
+	}
+	if (argc - optind < 2) errx(EX_USAGE, "host and chan required");
+	host = argv[optind];
+	chan = argv[optind + 1];
+
+	client = tls_client();
+	if (!client) errx(EX_SOFTWARE, "tls_client");
+
+	struct tls_config *config = tls_config_new();
+	if (!config) errx(EX_SOFTWARE, "tls_config_new");
+
+	if (cert) {
+		int error = tls_config_set_keypair_file(config, cert, cert);
+		if (error) errx(EX_CONFIG, "%s: %s", cert, tls_config_error(config));
+	}
+
+	int error = tls_configure(client, config);
+	if (error) errx(EX_SOFTWARE, "tls_configure: %s", tls_error(client));
+	tls_config_free(config);
+
+	error = tls_connect(client, host, port);
+	if (error) errx(EX_UNAVAILABLE, "tls_connect: %s", tls_error(client));
+
+	format(
+		"CAP REQ :message-tags%s\r\n"
+		"NICK %s\r\n"
+		"USER %s 0 * :typer\r\n",
+		(passive ? " causal.agency/passive" : ""),
+		nick, user
+	);
+
+	if (!copy && !reverse) {
+		signal(SIGALRM, timer);
+		struct itimerval itimer = {
+			.it_interval.tv_sec = 5,
+			.it_value.tv_sec = 5
+		};
+		error = setitimer(ITIMER_REAL, &itimer, NULL);
+		if (error) err(EX_OSERR, "setitimer");
+	}
+
+	size_t len = 0;
+	char buf[4096];
+	for (;;) {
+		ssize_t read = tls_read(client, &buf[len], sizeof(buf) - len);
+		if (read == TLS_WANT_POLLIN || read == TLS_WANT_POLLOUT) continue;
+		if (read < 0) errx(EX_IOERR, "tls_read: %s", tls_error(client));
+		if (!read) errx(EX_UNAVAILABLE, "server disconnected");
+		len += read;
+
+		char *crlf;
+		char *line = buf;
+		for (;;) {
+			crlf = memmem(line, &buf[len] - line, "\r\n", 2);
+			if (!crlf) break;
+			crlf[0] = '\0';
+			if (verbose) printf("%s\n", line);
+			handle(line);
+			line = &crlf[2];
+		}
+		len -= line - buf;
+		memmove(buf, line, len);
+	}
+}
diff --git a/bin/up.sh b/bin/up.sh
new file mode 100644
index 00000000..f55213d4
--- /dev/null
+++ b/bin/up.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+set -eu
+
+readonly Host='temp.causal.agency'
+
+upload() {
+	local src ext ts rand url
+	src=$1
+	ext=${src##*.}
+	ts=$(date +'%s')
+	rand=$(openssl rand -hex 4)
+	url=$(printf '%s/%x%s.%s' "$Host" "$ts" "$rand" "$ext")
+	scp -q "$src" "${Host}:/usr/local/www/${url}"
+	echo "https://${url}"
+}
+
+temp() {
+	temp=$(mktemp -d)
+	trap "rm -r '$temp'" EXIT
+}
+
+uploadText() {
+	temp
+	cat > "${temp}/input.txt"
+	upload "${temp}/input.txt"
+}
+
+uploadCommand() {
+	temp
+	echo "$ $*" > "${temp}/exec.txt"
+	"$@" >> "${temp}/exec.txt" 2>&1 || true
+	upload "${temp}/exec.txt"
+}
+
+uploadHilex() {
+	temp
+	hilex -f html -o document,tab=4 "$@" > "${temp}/hilex.html"
+	upload "${temp}/hilex.html"
+}
+
+uploadScreen() {
+	temp
+	if type screencapture >/dev/null; then
+		screencapture -i "$@" "${temp}/capture.png"
+	else
+		scrot -s "$@" "${temp}/capture.png"
+	fi
+	pngo "${temp}/capture.png" || true
+	upload "${temp}/capture.png"
+}
+
+uploadTerminal() {
+	temp
+	cat > "${temp}/term.html" <<-EOF
+	<!DOCTYPE html>
+	<title>${1}</title>
+	<style>
+	$(scheme -s)
+	</style>
+	EOF
+	ptee "$@" | shotty -Bs >> "${temp}/term.html"
+	upload "${temp}/term.html"
+}
+
+while getopts 'chst' opt; do
+	case "$opt" in
+		(c) fn=uploadCommand;;
+		(h) fn=uploadHilex;;
+		(s) fn=uploadScreen;;
+		(t) fn=uploadTerminal;;
+		(?) exit 1;;
+	esac
+done
+shift $((OPTIND - 1))
+[ $# -eq 0 ] && : ${fn:=uploadText}
+: ${fn:=upload}
+
+url=$($fn "$@")
+printf '%s' "$url" | pbcopy || true
+echo "$url"
diff --git a/bin/when.y b/bin/when.y
new file mode 100644
index 00000000..bba10c40
--- /dev/null
+++ b/bin/when.y
@@ -0,0 +1,250 @@
+/* Copyright (C) 2019  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+%{
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <sysexits.h>
+#include <time.h>
+
+static void yyerror(const char *str);
+static int yylex(void);
+
+#define YYSTYPE struct tm
+
+static const char *Days[7] = {
+	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+};
+
+static const char *Months[12] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+};
+
+static const struct tm Week = { .tm_mday = 7 };
+
+static struct tm normalize(struct tm date) {
+	time_t time = timegm(&date);
+	struct tm *norm = gmtime(&time);
+	if (!norm) err(EX_OSERR, "gmtime");
+	return *norm;
+}
+
+static struct tm today(void) {
+	time_t now = time(NULL);
+	struct tm *local = localtime(&now);
+	if (!local) err(EX_OSERR, "localtime");
+	struct tm date = {
+		.tm_year = local->tm_year,
+		.tm_mon = local->tm_mon,
+		.tm_mday = local->tm_mday,
+	};
+	return normalize(date);
+}
+
+static struct tm monthDay(int month, int day) {
+	struct tm date = today();
+	date.tm_mon = month;
+	date.tm_mday = day;
+	return normalize(date);
+}
+
+static struct tm monthDayYear(int month, int day, int year) {
+	struct tm date = today();
+	date.tm_mon = month;
+	date.tm_mday = day;
+	date.tm_year = year - 1900;
+	return normalize(date);
+}
+
+static struct tm weekDay(int day) {
+	struct tm date = today();
+	date.tm_mday += day - date.tm_wday;
+	return normalize(date);
+}
+
+static struct tm scalarAdd(struct tm a, struct tm b) {
+	a.tm_mday += b.tm_mday;
+	a.tm_mon += b.tm_mon;
+	a.tm_year += b.tm_year;
+	return a;
+}
+
+static struct tm scalarSub(struct tm a, struct tm b) {
+	a.tm_mday -= b.tm_mday;
+	a.tm_mon -= b.tm_mon;
+	a.tm_year -= b.tm_year;
+	return a;
+}
+
+static struct tm dateAdd(struct tm date, struct tm scalar) {
+	return normalize(scalarAdd(date, scalar));
+}
+
+static struct tm dateSub(struct tm date, struct tm scalar) {
+	return normalize(scalarSub(date, scalar));
+}
+
+static struct tm dateDiff(struct tm a, struct tm b) {
+	struct tm diff = {
+		.tm_year = a.tm_year - b.tm_year,
+		.tm_mon = a.tm_mon - b.tm_mon,
+		.tm_mday = a.tm_mday - b.tm_mday,
+	};
+	if (a.tm_mon < b.tm_mon) {
+		diff.tm_year--;
+		diff.tm_mon += 12;
+	}
+	if (a.tm_mday < b.tm_mday) {
+		diff.tm_mon--;
+		diff.tm_mday = 0;
+		while (dateAdd(b, diff).tm_mday != a.tm_mday) diff.tm_mday++;
+	}
+	time_t atime = timegm(&a), btime = timegm(&b);
+	diff.tm_yday = (atime - btime) / 24 / 60 / 60;
+	return diff;
+}
+
+static void printDate(struct tm date) {
+	printf(
+		"%s %s %d %d\n",
+		Days[date.tm_wday], Months[date.tm_mon],
+		date.tm_mday, 1900 + date.tm_year
+	);
+}
+
+static void printScalar(struct tm scalar) {
+	if (scalar.tm_year) printf("%dy ", scalar.tm_year);
+	if (scalar.tm_mon) printf("%dm ", scalar.tm_mon);
+	if (scalar.tm_mday % 7) {
+		printf("%dd ", scalar.tm_mday);
+	} else if (scalar.tm_mday) {
+		printf("%dw ", scalar.tm_mday / 7);
+	}
+	if (scalar.tm_yday && scalar.tm_mon) printf("(%dd) ", scalar.tm_yday);
+	printf("\n");
+}
+
+%}
+
+%token Number Month Day
+%left '+' '-'
+%right '<' '>'
+
+%%
+
+expr:
+	date { printDate($1); }
+	| scalar { printScalar($1); }
+	;
+
+date:
+	dateLit
+	| '(' date ')' { $$ = $2; }
+	| '<' date { $$ = dateSub($2, Week); }
+	| '>' date { $$ = dateAdd($2, Week); }
+	| date '+' scalar { $$ = dateAdd($1, $3); }
+	| date '-' scalar { $$ = dateSub($1, $3); }
+	;
+
+scalar:
+	scalarLit
+	| '(' scalar ')' { $$ = $2; }
+	| scalar '+' scalar { $$ = scalarAdd($1, $3); }
+	| scalar '-' scalar { $$ = scalarSub($1, $3); }
+	| date '-' date { $$ = dateDiff($1, $3); }
+	;
+
+dateLit:
+	{ $$ = today(); }
+	| '.' { $$ = today(); }
+	| Month Number { $$ = monthDay($1.tm_mon, $2.tm_sec); }
+	| Month Number Number { $$ = monthDayYear($1.tm_mon, $2.tm_sec, $3.tm_sec); }
+	| Day { $$ = weekDay($1.tm_wday); }
+	;
+
+scalarLit:
+	Number 'd' { $$ = (struct tm) { .tm_mday = $1.tm_sec }; }
+	| Number 'w' { $$ = (struct tm) { .tm_mday = 7 * $1.tm_sec }; }
+	| Number 'm' { $$ = (struct tm) { .tm_mon = $1.tm_sec }; }
+	| Number 'y' { $$ = (struct tm) { .tm_year = $1.tm_sec }; }
+	;
+
+%%
+
+static void yyerror(const char *str) {
+	warnx("%s", str);
+}
+
+static const char *input;
+
+static int yylex(void) {
+	while (isspace(*input)) input++;
+	if (!*input) return EOF;
+
+	if (isdigit(*input)) {
+		char *rest;
+		yylval.tm_sec = strtol(input, &rest, 10);
+		input = rest;
+		return Number;
+	}
+
+	for (int i = 0; i < 7; ++i) {
+		if (strncasecmp(input, Days[i], 3)) continue;
+		while (isalpha(*input)) input++;
+		yylval.tm_wday = i;
+		return Day;
+	}
+
+	for (int i = 0; i < 12; ++i) {
+		if (strncasecmp(input, Months[i], 3)) continue;
+		while (isalpha(*input)) input++;
+		yylval.tm_mon = i;
+		return Month;
+	}
+
+	return *input++;
+}
+
+int main(int argc, char *argv[]) {
+	if (argc > 1) {
+		input = argv[1];
+		return yyparse();
+	}
+
+	struct tm date = today();
+	printDate(date);
+	printf("\n");
+
+	char *line = NULL;
+	size_t cap = 0;
+	while (0 < getline(&line, &cap, stdin)) {
+		if (line[0] == '\n') continue;
+
+		if (today().tm_mday != date.tm_mday) {
+			warnx("the date has changed");
+			date = today();
+		}
+
+		input = line;
+		yyparse();
+		printf("\n");
+	}
+}
diff --git a/bin/xx.c b/bin/xx.c
new file mode 100644
index 00000000..39d7ec07
--- /dev/null
+++ b/bin/xx.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2017  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+typedef unsigned char byte;
+
+static bool zero(const byte *ptr, size_t size) {
+	for (size_t i = 0; i < size; ++i) {
+		if (ptr[i]) return false;
+	}
+	return true;
+}
+
+static struct {
+	size_t cols;
+	size_t group;
+	size_t blank;
+	bool ascii;
+	bool offset;
+	bool skip;
+} options = { 16, 8, 0, true, true, false };
+
+static void dump(FILE *file) {
+	bool skip = false;
+
+	byte buf[options.cols];
+	size_t offset = 0;
+	for (
+		size_t size;
+		(size = fread(buf, 1, sizeof(buf), file));
+		offset += size
+	) {
+		if (options.skip) {
+			if (zero(buf, size)) {
+				if (!skip) printf("*\n");
+				skip = true;
+				continue;
+			} else {
+				skip = false;
+			}
+		}
+
+		if (options.blank) {
+			if (offset && offset % options.blank == 0) {
+				printf("\n");
+			}
+		}
+
+		if (options.offset) {
+			printf("%08zX:  ", offset);
+		}
+
+		for (size_t i = 0; i < sizeof(buf); ++i) {
+			if (options.group) {
+				if (i && !(i % options.group)) {
+					printf(" ");
+				}
+			}
+			if (i < size) {
+				printf("%02hhX ", buf[i]);
+			} else {
+				printf("   ");
+			}
+		}
+
+		if (options.ascii) {
+			printf(" ");
+			for (size_t i = 0; i < size; ++i) {
+				if (options.group) {
+					if (i && !(i % options.group)) {
+						printf(" ");
+					}
+				}
+				printf("%c", isprint(buf[i]) ? buf[i] : '.');
+			}
+		}
+
+		printf("\n");
+	}
+}
+
+static void undump(FILE *file) {
+	byte c;
+	int match;
+	while (0 < (match = fscanf(file, " %hhx", &c))) {
+		printf("%c", c);
+	}
+	if (!match) errx(EX_DATAERR, "invalid input");
+}
+
+int main(int argc, char *argv[]) {
+	bool reverse = false;
+	const char *path = NULL;
+
+	int opt;
+	while (0 < (opt = getopt(argc, argv, "ac:g:p:rsz"))) {
+		switch (opt) {
+			break; case 'a': options.ascii ^= true;
+			break; case 'c': options.cols = strtoul(optarg, NULL, 0);
+			break; case 'g': options.group = strtoul(optarg, NULL, 0);
+			break; case 'p': options.blank = strtoul(optarg, NULL, 0);
+			break; case 'r': reverse = true;
+			break; case 's': options.offset ^= true;
+			break; case 'z': options.skip ^= true;
+			break; default: return EX_USAGE;
+		}
+	}
+	if (argc > optind) path = argv[optind];
+	if (!options.cols) return EX_USAGE;
+
+	FILE *file = path ? fopen(path, "r") : stdin;
+	if (!file) err(EX_NOINPUT, "%s", path);
+
+	if (reverse) {
+		undump(file);
+	} else {
+		dump(file);
+	}
+	if (ferror(file)) err(EX_IOERR, "%s", path);
+
+	return EX_OK;
+}
diff --git a/doc/pdf/.gitignore b/doc/pdf/.gitignore
new file mode 100644
index 00000000..a1363379
--- /dev/null
+++ b/doc/pdf/.gitignore
@@ -0,0 +1 @@
+*.pdf
diff --git a/doc/pdf/Makefile b/doc/pdf/Makefile
new file mode 100644
index 00000000..7afbdcf2
--- /dev/null
+++ b/doc/pdf/Makefile
@@ -0,0 +1,31 @@
+PDFS += abi.pdf
+PDFS += c11.pdf
+PDFS += elf.pdf
+PDFS += intel-64-opt.pdf
+PDFS += intel-64-sdm-vol-1.pdf
+PDFS += intel-64-sdm-vol-2.pdf
+PDFS += intel-64-sdm-vol-3.pdf
+PDFS += intel-64-sdm-vol-4.pdf
+PDFS += multiboot.pdf
+
+ELF = https://refspecs.linuxbase.org/elf
+INTEL = https://software.intel.com/sites/default/files/managed
+
+URL.abi.pdf = ${ELF}/x86_64-abi-0.99.pdf
+URL.c11.pdf = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+URL.elf.pdf = ${ELF}/elf.pdf
+URL.intel-64-opt.pdf = ${INTEL}/9e/bc/64-ia-32-architectures-optimization-manual.pdf
+URL.intel-64-sdm-vol-1.pdf = ${INTEL}/a4/60/253665-sdm-vol-1.pdf
+URL.intel-64-sdm-vol-2.pdf = ${INTEL}/a4/60/325383-sdm-vol-2abcd.pdf
+URL.intel-64-sdm-vol-3.pdf = ${INTEL}/a4/60/325384-sdm-vol-3abcd.pdf
+URL.intel-64-sdm-vol-4.pdf = ${INTEL}/22/0d/335592-sdm-vol-4.pdf
+URL.multiboot.pdf = https://www.gnu.org/software/grub/manual/multiboot/multiboot.pdf
+
+all: ${PDFS}
+
+${PDFS}:
+	curl -Lf -o $@ ${URL.$@}
+	chmod a-w $@
+
+clean:
+	rm -f ${PDFS}
diff --git a/doc/rfc/.gitignore b/doc/rfc/.gitignore
new file mode 100644
index 00000000..cc3245d4
--- /dev/null
+++ b/doc/rfc/.gitignore
@@ -0,0 +1,2 @@
+rfc
+rfctags
diff --git a/doc/rfc/Makefile b/doc/rfc/Makefile
new file mode 100644
index 00000000..31e238a0
--- /dev/null
+++ b/doc/rfc/Makefile
@@ -0,0 +1,38 @@
+PREFIX ?= ~/.local
+MANDIR ?= ${PREFIX}/share/man
+
+MODULE = ftp.rfc-editor.org::rfcs-text-only
+RFCS = ${MODULE}/rfc-index.txt ${MODULE}/'rfc[1-9]*.txt'
+
+all: rfc rfctags
+
+.SUFFIXES: .in .pl
+
+.in:
+	sed 's|%%PREFIX%%|${PREFIX}|g' $< > $@
+	chmod a+x $@
+
+.pl:
+	cp -f $< $@
+	chmod a+x $@
+
+clean:
+	rm -f rfc rfctags
+
+install: rfc rfctags rfc.1
+	install -d ${PREFIX}/bin ${MANDIR}/man1
+	install rfc rfctags ${PREFIX}/bin
+	install -m 644 rfc.1 ${MANDIR}/man1
+	ln -fs rfc.1 ${MANDIR}/man1/rfctags.1
+
+sync:
+	install -d ${PREFIX}/share
+	rsync -ptz ${RFCS} ${PREFIX}/share/rfc
+
+compress:
+	find ${PREFIX}/share/rfc -name '*.txt' | xargs gzip -9f
+
+uninstall:
+	rm -f ${PREFIX}/bin/rfc ${PREFIX}/bin/rfctags
+	rm -f ${MANDIR}/man1/rfc.1 ${MANDIR}/man1/rfctags.1
+	rm -fr ${PREFIX}/share/rfc
diff --git a/doc/rfc/rfc.1 b/doc/rfc/rfc.1
new file mode 100644
index 00000000..ece5a901
--- /dev/null
+++ b/doc/rfc/rfc.1
@@ -0,0 +1,53 @@
+.Dd January 18, 2021
+.Dt RFC 1
+.Os
+.
+.Sh NAME
+.Nm rfc ,
+.Nm rfctags
+.Nd view IETF RFCs
+.
+.Sh SYNOPSIS
+.Nm rfc
+.Op Ar number
+.Nm rfctags
+.Op Ar
+.
+.Sh DESCRIPTION
+The
+.Nm rfc
+utility displays
+an IETF RFC by number,
+or the RFC index if no number is specified.
+The RFC is displayed in the
+.Ev PAGER
+with a tags file generated by
+.Nm rfctags .
+.
+.Pp
+The
+.Nm rfctags
+utility generates tags
+for RFC text file
+section numbers,
+section names
+and bracketed references.
+.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev PAGER
+The program used to display RFCs.
+It must accept the
+.Fl T
+flag for specifying
+the path of the tags file.
+The default is
+.Ev PAGER=less .
+.El
+.
+.Sh SEE ALSO
+.Xr ctags 1 ,
+.Xr less 1
+.
+.Sh AUTHORS
+.An June Bug Aq Mt june@causal.agency
diff --git a/doc/rfc/rfc.in b/doc/rfc/rfc.in
new file mode 100644
index 00000000..16081c83
--- /dev/null
+++ b/doc/rfc/rfc.in
@@ -0,0 +1,19 @@
+#!/bin/sh
+set -eu
+
+mktemp='mktemp -t rfc'
+[ "$(uname)" = 'OpenBSD' ] && mktemp="${mktemp}.XXXXXXXXXX"
+
+rfc=%%PREFIX%%/share/rfc/"rfc${1:--index}.txt"
+tags=$($mktemp)
+trap 'rm "${tags}"' EXIT
+
+if test -f "${rfc}.gz"; then
+	txt=$($mktemp)
+	trap 'rm "${txt}" "${tags}"' EXIT
+	gunzip -c "${rfc}.gz" >"${txt}"
+	rfc=$txt
+fi
+
+%%PREFIX%%/bin/rfctags "${rfc}" >"${tags}"
+${PAGER:-less} -T "${tags}" "${rfc}"
diff --git a/doc/rfc/rfctags.pl b/doc/rfc/rfctags.pl
new file mode 100644
index 00000000..05173d00
--- /dev/null
+++ b/doc/rfc/rfctags.pl
@@ -0,0 +1,21 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use open ':encoding(ISO-8859-1)';
+
+($,, $\) = ("\t", "\n");
+while (<>) {
+	chomp;
+	# Section headings
+	if (/^([\d.]+|[A-Z][.])\s+([^\t]+)?/) {
+		print $1, $ARGV, $.;
+		print $2, $ARGV, $. if $2;
+		print $1, $ARGV, $. if $1 =~ /^([\d.]+)[.]$/;
+	}
+	# References
+	if (/^\s*(\[[\w-]+\])\s{2,}/) {
+		print $1, $ARGV, $.;
+		print "\\$1", $ARGV, $.; # vim ^] prepends \ to [
+	}
+	close ARGV if eof;
+}
diff --git a/doc/zlib/Makefile b/doc/zlib/Makefile
new file mode 100644
index 00000000..6cfd4a42
--- /dev/null
+++ b/doc/zlib/Makefile
@@ -0,0 +1,87 @@
+PREFIX ?= ~/.local
+MANDIR ?= ${PREFIX}/share/man
+
+MAN += adler32.3
+MAN += adler32_combine.3
+MAN += compress.3
+MAN += compressBound.3
+MAN += crc32.3
+MAN += crc32_combine.3
+MAN += deflate.3
+MAN += deflateBound.3
+MAN += deflateCopy.3
+MAN += deflateEnd.3
+MAN += deflateGetDictionary.3
+MAN += deflateInit.3
+MAN += deflateInit2.3
+MAN += deflateParams.3
+MAN += deflatePending.3
+MAN += deflatePrime.3
+MAN += deflateReset.3
+MAN += deflateSetDictionary.3
+MAN += deflateSetHeader.3
+MAN += deflateTune.3
+MAN += gzbuffer.3
+MAN += gzclose.3
+MAN += gzdirect.3
+MAN += gzeof.3
+MAN += gzerror.3
+MAN += gzflush.3
+MAN += gzfread.3
+MAN += gzfwrite.3
+MAN += gzgetc.3
+MAN += gzgets.3
+MAN += gzoffset.3
+MAN += gzopen.3
+MAN += gzprintf.3
+MAN += gzputc.3
+MAN += gzputs.3
+MAN += gzread.3
+MAN += gzseek.3
+MAN += gzsetparams.3
+MAN += gzungetc.3
+MAN += gzwrite.3
+MAN += inflate.3
+MAN += inflateBack.3
+MAN += inflateBackEnd.3
+MAN += inflateBackInit.3
+MAN += inflateCopy.3
+MAN += inflateEnd.3
+MAN += inflateGetDictionary.3
+MAN += inflateGetHeader.3
+MAN += inflateInit.3
+MAN += inflateInit2.3
+MAN += inflateMark.3
+MAN += inflatePrime.3
+MAN += inflateReset.3
+MAN += inflateSetDictionary.3
+MAN += inflateSync.3
+MAN += uncompress.3
+MAN += zlibCompileFlags.3
+MAN += zlibVersion.3
+
+MLINKS += adler32.3 adler32_z.3
+MLINKS += compress.3 compress2.3
+MLINKS += crc32.3 crc32_z.3
+MLINKS += gzclose.3 gzclose_r.3
+MLINKS += gzclose.3 gzclose_w.3
+MLINKS += gzerror.3 gzclearerr.3
+MLINKS += gzopen.3 gzdopen.3
+MLINKS += gzseek.3 gzrewind.3
+MLINKS += gzseek.3 gztell.3
+MLINKS += inflateReset.3 inflateReset2.3
+MLINKS += uncompress.3 uncompress2.3
+
+lint:
+	mandoc -T lint ${MAN} | grep -v 'referenced manual not found'
+
+install:
+	install -d ${MANDIR}/man3
+	install -m 644 ${MAN} ${MANDIR}/man3
+	set -- ${MLINKS}; while [ -n "$$*" ]; do \
+		ln -fs $$1 ${MANDIR}/man3/$$2; shift 2; done
+
+uninstall:
+	rm -f ${MAN:%=${MANDIR}/man3/%}
+	set -- ${MLINKS}; while [ -n "$$*" ]; do \
+		rm -f ${MANDIR}/man3/$$2; shift 2; done
diff --git a/doc/zlib/adler32.3 b/doc/zlib/adler32.3
new file mode 100644
index 00000000..c58a34e7
--- /dev/null
+++ b/doc/zlib/adler32.3
@@ -0,0 +1,65 @@
+.Dd January 15, 2017
+.Dt ADLER32 3
+.Os
+.
+.Sh NAME
+.Nm adler32 ,
+.Nm adler32_z
+.Nd update Adler-32 checksum
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft uLong
+.Fn adler32 "uLong adler" "const Bytef *buf" "uInt len"
+.Ft uLong
+.Fn adler32_z "uLong adler" "const Bytef *buf" "z_size_t len"
+.
+.Sh DESCRIPTION
+Update a running Adler-32 checksum with the bytes
+.Fa "buf[0..len-1]"
+and return the updated checksum.
+If
+.Fa buf
+is
+.Dv Z_NULL ,
+this function returns
+the required initial value for the checksum.
+.
+.Pp
+An Adler-32 checksum is almost as reliable as a CRC-32
+but can be computed much faster.
+.
+.Pp
+.Fn adler32_z
+is the same as
+.Fn adler32 ,
+but with a
+.Vt size_t
+length.
+.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+uLong adler = adler32(0L, Z_NULL, 0);
+
+while (read_buffer(buffer, length) != EOF) {
+	adler = adler32(adler, buffer, length);
+}
+if (adler != original_adler) error();
+.Ed
+.
+.Sh SEE ALSO
+.Xr adler32_combine 3 ,
+.Xr crc32 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/adler32_combine.3 b/doc/zlib/adler32_combine.3
new file mode 100644
index 00000000..55e801e9
--- /dev/null
+++ b/doc/zlib/adler32_combine.3
@@ -0,0 +1,63 @@
+.Dd January 15, 2017
+.Dt ADLER32_COMBINE 3
+.Os
+.
+.Sh NAME
+.Nm adler32_combine
+.Nd combine Adler-32 checksums
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft uLong
+.Fn adler32_combine "uLong adler1" "uLong adler2" "z_off_t len2"
+.
+.Sh DESCRIPTION
+Combine two Adler-32 checksums into one.
+For two sequences of bytes,
+.Va seq1
+and
+.Va seq2
+with lengths
+.Va len1
+and
+.Va len2 ,
+Adler-32 checksums were calculated for each,
+.Va adler1
+and
+.Va adler2 .
+.Fn adler32_combine
+returns the Adler-32 checksum of
+.Va seq1
+and
+.Va seq2
+concatenated,
+requiring only
+.Fa adler1 ,
+.Fa adler2 ,
+and
+.Fa len2 .
+Note that the
+.Vt z_off_t
+type
+.Pq like Vt off_t
+is a signed integer.
+If
+.Fa len2
+is negative,
+the result has no meaning or utility.
+.
+.Sh SEE ALSO
+.Xr adler32 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/compress.3 b/doc/zlib/compress.3
new file mode 100644
index 00000000..16445e2f
--- /dev/null
+++ b/doc/zlib/compress.3
@@ -0,0 +1,84 @@
+.Dd January 15, 2017
+.Dt COMPRESS 3
+.Os
+.
+.Sh NAME
+.Nm compress ,
+.Nm compress2
+.Nd compress source buffer into destination buffer
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.
+.Ft int
+.Fo compress
+.Fa "Bytef *dest"
+.Fa "uLongf *destLen"
+.Fa "const Bytef *source"
+.Fa "uLong sourceLen"
+.Fc
+.
+.Ft int
+.Fo compress2
+.Fa "Bytef *dest"
+.Fa "uLongf *destLen"
+.Fa "const Bytef *source"
+.Fa "uLong sourceLen"
+.Fa "int level"
+.Fc
+.
+.Sh DESCRIPTION
+Compresses the source buffer into the destination buffer.
+.Fa sourceLen
+is the byte length of the source buffer.
+Upon entry,
+.Fa destLen
+is the total size of the destination buffer,
+which must be at least the value returned by
+.Fn compressBound sourceLen .
+Upon exit,
+.Fa destLen
+is the actual size of the compressed data.
+.
+.Pp
+.Fn compress
+is equivalent to
+.Fn compress2
+with a
+.Fa level
+parameter of
+.Dv Z_DEFAULT_COMPRESSION .
+.
+.Sh RETURN VALUES
+.Fn compress
+and
+.Fn compress2
+return
+.Dv Z_OK
+on success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_BUF_ERROR
+if there was not enough room in the output buffer,
+.Dv Z_STREAM_ERROR
+if the
+.Fa level
+parameter is invalid.
+.
+.Sh SEE ALSO
+.Xr compressBound 3 ,
+.Xr deflateInit 3 ,
+.Xr uncompress 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/compressBound.3 b/doc/zlib/compressBound.3
new file mode 100644
index 00000000..d61891eb
--- /dev/null
+++ b/doc/zlib/compressBound.3
@@ -0,0 +1,44 @@
+.Dd January 15, 2017
+.Dt COMPRESSBOUND 3
+.Os
+.
+.Sh NAME
+.Nm compressBound
+.Nd compressed size upper bound
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft uLong
+.Fn compressBound "uLong sourceLen"
+.
+.Sh DESCRIPTION
+.Fn compressBound
+returns an upper bound on the compressed size after
+.Xr compress 3
+or
+.Xr compress2 3
+on
+.Fa sourceLen
+bytes.
+It would be used before a
+.Xr compress 3
+or
+.Xr compress2 3
+call to allocate the destination buffer.
+.
+.Sh SEE ALSO
+.Xr compress 3 ,
+.Xr deflateBound 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/crc32.3 b/doc/zlib/crc32.3
new file mode 100644
index 00000000..a42df2af
--- /dev/null
+++ b/doc/zlib/crc32.3
@@ -0,0 +1,66 @@
+.Dd January 15, 2017
+.Dt CRC32 3
+.Os
+.
+.Sh NAME
+.Nm crc32 ,
+.Nm crc32_z
+.Nd update CRC-32 checksum
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft uLong
+.Fn crc32 "uLong crc" "const Bytef *buf" "uInt len"
+.Ft uLong
+.Fn crc32_z "uLong crc" "const Bytef *buf" "z_size_t len"
+.
+.Sh DESCRIPTION
+Update a running CRC-32 with the bytes
+.Fa "buf[0..len-1]"
+and return the updated CRC-32.
+If
+.Fa buf
+is
+.Dv Z_NULL ,
+this function returns
+the required initial value for the CRC.
+Pre- and post-conditioning
+(one's complement)
+is performed within this function
+so it shouldn't be done
+by the application.
+.
+.Pp
+.Fn crc32_z
+is the same as
+.Fn crc32 ,
+but with a
+.Vt size_t
+length.
+.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+uLong crc = crc32(0L, Z_NULL, 0);
+
+while (read_buffer(buffer, length) != EOF) {
+	crc = crc32(crc, buffer, length);
+}
+if (crc != original_crc) error();
+.Ed
+.
+.Sh SEE ALSO
+.Xr adler32 3 ,
+.Xr crc32_combine 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/crc32_combine.3 b/doc/zlib/crc32_combine.3
new file mode 100644
index 00000000..b25da679
--- /dev/null
+++ b/doc/zlib/crc32_combine.3
@@ -0,0 +1,54 @@
+.Dd January 15, 2017
+.Dt CRC32_COMBINE 3
+.Os
+.
+.Sh NAME
+.Nm crc32_combine
+.Nd combine CRC-32 checksums
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft uLong
+.Fn crc32_combine "uLong crc1" "uLong crc2" "z_off_t len2"
+.
+.Sh DESCRIPTION
+Combine two CRC-32 check values into one.
+For two sequences of bytes,
+.Va seq1
+and
+.Va seq2
+with lengths
+.Va len1
+and
+.Va len2 ,
+CRC-32 check values were calculated for each,
+.Va crc1
+and
+.Va crc2 .
+.Fn crc32_combine
+returns the CRC-32 check value of
+.Va seq1
+and
+.Va seq2
+concatenated,
+requiring only
+.Fa crc1 ,
+.Fa crc2 ,
+and
+.Fa len2 .
+.
+.Sh SEE ALSO
+.Xr crc32 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflate.3 b/doc/zlib/deflate.3
new file mode 100644
index 00000000..be182d96
--- /dev/null
+++ b/doc/zlib/deflate.3
@@ -0,0 +1,370 @@
+.Dd January 15, 2017
+.Dt DEFLATE 3
+.Os
+.
+.Sh NAME
+.Nm deflate
+.Nd deflate compression
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn deflate "z_streamp strm" "int flush"
+.
+.Sh DESCRIPTION
+.Fn deflate
+compresses as much data as possible,
+and stops when the input buffer becomes empty
+or the output buffer becomes full.
+It may introduce some output latency
+(reading input without producing any output)
+except when forced the flush.
+.
+.Pp
+The detailed semantics are as follows.
+.Fn deflate
+performs one or both of the following actions:
+.
+.Bl -dash
+.It
+Compress more input starting at
+.Fa next_in
+and update
+.Fa next_in
+and
+.Fa avail_in
+accordingly.
+If not all input can be processed
+(because there is not enough room in the output buffer),
+.Fa next_in
+and
+.Fa avail_in
+are updated
+and processing will resume at this point
+for the next call of
+.Fn deflate .
+.
+.It
+Generate more output starting at
+.Fa next_out
+and update
+.Fa next_out
+and
+.Fa avail_out
+accordingly.
+This action is forced if the parameter
+.Fa flush
+is non-zero.
+Forcing flush frequently degrades the compression ratio,
+so this parameter should be set only when necessary.
+Some output may be provided even if
+.Fa flush
+is zero.
+.El
+.
+.Pp
+Before the call of
+.Fn deflate ,
+the application should ensure that
+at least one of the actions is possible,
+by providing more input
+and/or consuming more output,
+and updating
+.Fa avail_in
+or
+.Fa avail_out
+accordingly;
+.Fa avail_out
+should never be zero before the call.
+The application can consume the compressed output
+when it wants,
+for example when the output buffer is full
+.Po
+.Fa avail_out
+== 0
+.Pc ,
+or after each call of
+.Fn deflate .
+If
+.Fn deflate
+returns
+.Dv Z_OK
+and with zero
+.Fa avail_out ,
+it must be called again after making room in the output buffer
+because there might be more output pending.
+See
+.Xr deflatePending 3 ,
+which can be used if desired to determine
+whether or not there is more output in that case.
+.
+.Pp
+Normally the parameter
+.Fa flush
+is set to
+.Dv Z_NO_FLUSH ,
+which allows
+.Fn deflate
+to decide how much data to accumulate before producing output,
+in order to maximize compression.
+.
+.Pp
+If the parameter
+.Fa flush
+is set to
+.Dv Z_SYNC_FLUSH ,
+all pending output is flushed to the output buffer
+and the output is aligned on a byte boundary,
+so that the decompressor can get all input data available so far.
+.Po
+In particular
+.Fa avail_in
+is zero after the call if enough output space
+has been provided before the call.
+.Pc \&
+Flushing may degrade compression for some compression algorithms
+and so it should be used only when necessary.
+This completes the current deflate block
+and follows it with an empty stored block
+that is three bits plus filler bits to the next byte,
+followed by four bytes
+(00 00 ff ff).
+.
+.Pp
+If
+.Fa flush
+is set to
+.Dv Z_PARTIAL_FLUSH ,
+all pending output is flushed to the output buffer,
+but the output is not aligned to a byte boundary.
+All of the input data so far will be available to the decompressor,
+as for
+.Dv Z_SYNC_FLUSH .
+This completes the current deflate block
+and follows it with an empty fixed codes block
+that is 10 bits long.
+This assures that enough bytes are output
+in order for the decompressor to finish the block
+before the empty fixed codes block.
+.
+.Pp
+If
+.Fa flush
+is set to
+.Dv Z_BLOCK ,
+a deflate block is completed and emitted,
+as for
+.Dv Z_SYNC_FLUSH ,
+but the output is not aligned on a byte boundary,
+and up to seven bits of the current block
+are held to be written as the next byte
+after the next deflate block is completed.
+In this case,
+the decompressor may not be provided enough bits
+at this point in order to complete decompression
+of the data provided so far to the compressor.
+It may need to wait for the next block to be emitted.
+This is for advanced applications
+that need to control the emission of deflate blocks.
+.
+.Pp
+If
+.Fa flush
+is set to
+.Dv Z_FULL_FLUSH ,
+all output is flushed as with
+.Dv Z_SYNC_FLUSH ,
+and the compression state is reset
+so that decompression can restart from this point
+if previous compressed data has been damaged
+or if random access is desired.
+Using
+.Dv Z_FULL_FLUSH
+too often can seriously degrade compression.
+.
+.Pp
+If
+.Fn deflate
+returns with
+.Fa avail_out
+== 0,
+this function must be called again
+with the same value of the
+.Fa flush
+parameter
+and more output space
+.Po
+updated
+.Fa avail_out
+.Pc ,
+until the flush is complete
+.Po
+.Fn deflate
+returns with non-zero
+.Fa avail_out
+.Pc .
+In the case of a
+.Dv Z_FULL_FLUSH
+or
+.Dv Z_SYNC_FLUSH ,
+make sure that
+.Fa avail_out
+is greater than six
+to avoid repeated flush markers
+due to
+.Fa avail_out
+== 0
+on return.
+.
+.Pp
+If the parameter
+.Fa flush
+is set to
+.Dv Z_FINISH ,
+pending input is processed,
+pending output is flushed and
+.Fn deflate
+returns with
+.Dv Z_STREAM_END
+if there was enough output space.
+If
+.Fn deflate
+returns with
+.Dv Z_OK
+or
+.Dv Z_BUF_ERROR ,
+this function must be called again with
+.Dv Z_FINISH
+and more output space
+.Pq updated Fa avail_out
+but no more input data,
+until it returns with
+.Dv Z_STREAM_END
+or an error.
+After
+.Fn deflate
+has returned
+.Dv Z_STREAM_END ,
+the only possible operations on the stream are
+.Xr deflateReset 3
+or
+.Xr deflateEnd 3 .
+.
+.Pp
+.Dv Z_FINISH
+can be used in the first
+.Fn deflate
+call after
+.Xr deflateInit 3
+if all the compression is to be done in a single step.
+In order to complete in one call,
+.Fa avail_out
+must be at least the value returned by
+.Xr deflateBound 3 .
+Then
+.Fn deflate
+is guaranteed to return
+.Dv Z_STREAM_END .
+If not enough output space is provided,
+.Fn deflate
+will not return
+.Dv Z_STREAM_END ,
+and it must be called again as described above.
+.
+.Pp
+.Fn deflate
+sets
+.Fa strm->adler
+to the Adler-32 checksum
+of all input read so far
+.Po
+that is,
+.Fa total_in
+bytes
+.Pc .
+If a gzip stream is being generated,
+then
+.Fa strm->adler
+will be the CRC-32 checksum of the input read so far.
+See
+.Xr deflateInit2 3 .
+.
+.Pp
+.Fn deflate
+may update
+.Fa strm->data_type
+if it can make a good guess
+about the input data type
+.Po
+.Dv Z_BINARY
+or
+.Dv Z_TEXT
+.Pc .
+If in doubt,
+the date is considered binary.
+This field is only for information purposes
+and does not affect the compression algorithm in any manner.
+.
+.Sh RETURN VALUES
+.Fn deflate
+returns
+.Dv Z_OK
+if some progress has been made
+(more input processed or more output produced),
+.Dv Z_STREAM_END
+if all input has been consumed
+and all output has been produced
+.Po
+only when
+.Fa flush
+is set to
+.Dv Z_FINISH
+.Pc ,
+.Dv Z_STREAM_ERROR
+if the stream state was inconsistent
+.Po
+for example if
+.Fa next_in
+or
+.Fa next_out
+was
+.Dv Z_NULL
+or the state was inadvertently written over
+by the application
+.Pc ,
+or
+.Dv Z_BUF_ERROR
+if no progress is possible
+.Po
+for example
+.Fa avail_in
+or
+.Fa avail_out
+was zero
+.Pc .
+Note that
+.Dv Z_BUF_ERROR
+is not fatal,
+and
+.Fn deflate
+can be called again with more input and more output space
+to continue compressing.
+.
+.Sh SEE ALSO
+.Xr deflateEnd 3 ,
+.Xr deflateInit 3 ,
+.Xr deflatePending 3 ,
+.Xr inflate 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateBound.3 b/doc/zlib/deflateBound.3
new file mode 100644
index 00000000..be97494c
--- /dev/null
+++ b/doc/zlib/deflateBound.3
@@ -0,0 +1,71 @@
+.Dd January 15, 2017
+.Dt DEFLATEBOUND 3
+.Os
+.
+.Sh NAME
+.Nm deflateBound
+.Nd compressed size upper bound
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft uLong
+.Fn deflateBound "z_streamp strm" "uLong sourceLen"
+.
+.Sh DESCRIPTION
+.Fn deflateBound
+returns an upper bound
+on the compressed size
+after deflation of
+.Fa sourceLen
+bytes.
+It must be called after
+.Xr deflateInit 3
+or
+.Xr deflateInit2 3 ,
+and after
+.Xr deflateSetHeader 3 ,
+if used.
+This would be used
+to allocate an output buffer
+for deflation in a single pass,
+and so would be called before
+.Xr deflate 3 .
+If that first
+.Fn deflate
+call is provided the
+.Fa sourceLen
+input bytes,
+an output buffer allocated
+to the size returned by
+.Fn deflateBound ,
+and the flush value
+.Dv Z_FINISH ,
+then
+.Fn deflate
+is guaranteed to return
+.Dv Z_STREAM_END .
+Note that it is possible
+for the compressed size
+to be larger than the value returned by
+.Fn deflateBound
+if flush options other than
+.Dv Z_FINISH
+or
+.Dv Z_NO_FLUSH
+are used.
+.
+.Sh SEE ALSO
+.Xr compressBound 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateCopy.3 b/doc/zlib/deflateCopy.3
new file mode 100644
index 00000000..f20e0a9e
--- /dev/null
+++ b/doc/zlib/deflateCopy.3
@@ -0,0 +1,66 @@
+.Dd January 15, 2017
+.Dt DEFLATECOPY 3
+.Os
+.
+.Sh NAME
+.Nm deflateCopy
+.Nd copy deflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn deflateCopy "z_streamp dest" "z_streamp source"
+.
+.Sh DESCRIPTION
+Sets the destination stream
+as a complete copy of the source stream.
+.
+.Pp
+This function can be useful when
+several compression strategies will be tried,
+for example when there are several ways of
+pre-processing the input data with a filter.
+The streams that will be discarded
+should then be freed by calling
+.Xr deflateEnd 3 .
+Note that
+.Fn deflateCopy
+duplicates the internal compression state
+which can be quite large,
+so this strategy is slow
+and can consume lots of memory.
+.
+.Sh RETURN VALUES
+.Fn deflateCopy
+returns
+.Dv Z_OK
+if success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent
+.Po
+such as
+.Fa zalloc
+being
+.Dv Z_NULL
+.Pc .
+.Fa msg
+is left unchanged
+in both source and destination.
+.
+.Sh SEE ALSO
+.Xr deflateInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateEnd.3 b/doc/zlib/deflateEnd.3
new file mode 100644
index 00000000..0abaabe1
--- /dev/null
+++ b/doc/zlib/deflateEnd.3
@@ -0,0 +1,50 @@
+.Dd January 15, 2017
+.Dt DEFLATEEND 3
+.Os
+.
+.Sh NAME
+.Nm deflateEnd
+.Nd free deflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn deflateEnd "z_streamp strm"
+.
+.Sh DESCRIPTION
+All dynamically allocated data structures
+for this stream are freed.
+This function discards any unprocessed input
+and does not flush any pending output.
+.
+.Sh RETURN VALUES
+.Fn deflateEnd
+returns
+.Dv Z_OK
+if success,
+.Dv Z_STREAM_ERROR
+if the stream state was inconsistent,
+.Dv Z_DATA_ERROR
+if the stream was freed prematurely
+(some input or output was discarded).
+In the error case,
+.Fa msg
+may be set but then points to a static string
+(which must not be deallocated).
+.
+.Sh SEE ALSO
+.Xr deflate 3 ,
+.Xr deflateInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateGetDictionary.3 b/doc/zlib/deflateGetDictionary.3
new file mode 100644
index 00000000..b9dabfe2
--- /dev/null
+++ b/doc/zlib/deflateGetDictionary.3
@@ -0,0 +1,79 @@
+.Dd January 15, 2017
+.Dt DEFLATEGETDICTIONARY 3
+.Os
+.
+.Sh NAME
+.Nm deflateGetDictionary
+.Nd deflate sliding dictionary
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fo deflateGetDictionary
+.Fa "z_streamp strm"
+.Fa "Bytef *dictionary"
+.Fa "uInt *dictLength"
+.Fc
+.
+.Sh DESCRIPTION
+Returns the sliding dictionary
+being maintained by deflate.
+.Fa dictLength
+is set to the number of bytes in the dictionary,
+and that many bytes are copied to
+.Fa dictionary .
+.Fa dictionary
+must have enough space,
+where 32768 bytes is always enough.
+If
+.Fn deflateGetDictionary
+is called with
+.Fa dictionary
+equal to
+.Dv Z_NULL ,
+then only the dictionary length is returned,
+and nothing is copied.
+Similarly,
+if
+.Fa dictLength
+is
+.Dv Z_NULL ,
+then it is not set.
+.
+.Pp
+.Fn deflateGetDictionary
+may return a length less than the window size,
+even when more than the window size in input
+has been provided.
+It may return up to 258 bytes less in that case,
+due to how zlib's implementation of deflate
+manages the sliding window and lookahead for matches,
+where matches can be up to 258 bytes long.
+If the application needs the last window-size bytes of input,
+then that would need to be saved by the application
+outside of zlib.
+.
+.Sh RETURN VALUES
+.Fn deflateGetDictionary
+returns
+.Dv Z_OK
+on success,
+or
+.Dv Z_STREAM_ERROR
+if the stream state is inconsistent.
+.
+.Sh SEE ALSO
+.Xr deflateSetDictionary 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateInit.3 b/doc/zlib/deflateInit.3
new file mode 100644
index 00000000..52179883
--- /dev/null
+++ b/doc/zlib/deflateInit.3
@@ -0,0 +1,178 @@
+.Dd January 15, 2017
+.Dt DEFLATEINIT 3
+.Os
+.
+.Sh NAME
+.Nm deflateInit
+.Nd initialize deflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.
+.Ft typedef voidpf
+.Fo (*alloc_func)
+.Fa "voidpf opaque"
+.Fa "uInt items"
+.Fa "uInt size"
+.Fc
+.
+.Ft typedef void
+.Fo (*free_func)
+.Fa "voidpf opaque"
+.Fa "voidpf address"
+.Fc
+.
+.Bd -literal
+typedef struct z_stream_s {
+	z_const Bytef *next_in;
+	uInt     avail_in;
+	uLong    total_in;
+
+	Bytef    *next_out;
+	uInt     avail_out;
+	uLong    total_out;
+
+	z_const char *msg;
+	struct internal_state FAR *state;
+
+	alloc_func zalloc;
+	free_func  zfree;
+	voidpf     opaque;
+
+	int     data_type;
+	uLong   adler;
+	uLong   reserved;
+} z_stream;
+.Ed
+.
+.Pp
+.Vt typedef z_stream FAR *z_streamp;
+.
+.Ft int
+.Fn deflateInit "z_streamp strm" "int level"
+.
+.Sh DESCRIPTION
+Initializes the internal stream state for compression.
+The fields
+.Fa zalloc ,
+.Fa zfree
+and
+.Fa opaque
+must be initialized before by the caller.
+If
+.Fa zalloc
+and
+.Fa zfree
+are set to
+.Dv Z_NULL ,
+.Fn deflateInit
+updates them to use default allocation functions.
+.Fn deflateInit
+does not perform any compression:
+this will be done by
+.Xr deflate 3 .
+.
+.Pp
+The compression
+.Fa level
+must be
+.Dv Z_DEFAULT_COMPRESSION ,
+or between 0 and 9:
+1 gives best speed,
+9 gives best compression,
+0 gives no compression at all
+(the input data is simply copied a block at a time).
+.Dv Z_DEFAULT_COMPRESSION
+requests a default compromise between speed and compression
+(currently equivalent to level 6).
+.
+.Pp
+The fields of
+.Vt z_stream
+are as follows:
+.
+.Bl -tag -width "data_type"
+.It Fa next_in
+next input byte
+.It Fa avail_in
+number of bytes available at
+.Fa next_in
+.It Fa total_in
+total number of input bytes read so far
+.It Fa next_out
+next output byte will go here
+.It Fa avail_out
+remaining free space at
+.Fa next_out
+.It Fa total_out
+total number of bytes output so far
+.It Fa msg
+last error message,
+.Dv NULL
+if no error
+.It Fa state
+not visible by applications
+.It Fa zalloc
+used to allocate the internal state
+.It Fa zfree
+used to free the internal state
+.It Fa opaque
+private data object passed to
+.Fa zalloc
+and
+.Fa zfree
+.It data_type
+best guess about the data type:
+binary or text for
+.Xr deflate 3 ,
+or the decoding state for
+.Xr inflate 3
+.It adler
+Adler-32 or CRC-32 value of the uncompressed data
+.It reserved
+reserved for future use
+.El
+.
+.Sh RETURN VALUES
+.Fn deflateInit
+returns
+.Dv Z_OK
+if success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_STREAM_ERROR
+if
+.Fa level
+is not a valid compression level,
+or
+.Dv Z_VERSION_ERROR
+if the zlib library version
+.Pq Xr zlibVersion 3
+is incompatible with the version assumed by the caller
+.Pq Dv ZLIB_VERSION .
+.Fa msg
+is set to null
+if there is no error message.
+.
+.Sh SEE ALSO
+.Xr deflate 3 ,
+.Xr deflateCopy 3 ,
+.Xr deflateEnd 3 ,
+.Xr deflateInit2 3 ,
+.Xr deflatePrime 3 ,
+.Xr deflateReset 3 ,
+.Xr deflateSetDictionary 3 ,
+.Xr deflateTune 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateInit2.3 b/doc/zlib/deflateInit2.3
new file mode 100644
index 00000000..a7d68b99
--- /dev/null
+++ b/doc/zlib/deflateInit2.3
@@ -0,0 +1,227 @@
+.Dd January 15, 2017
+.Dt DEFLATEINIT2 3
+.Os
+.
+.Sh NAME
+.Nm deflateInit2
+.Nd deflate compression options
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fo deflateInit2
+.Fa "z_streamp strm"
+.Fa "int level"
+.Fa "int method"
+.Fa "int windowBits"
+.Fa "int memLevel"
+.Fa "int strategy"
+.Fc
+.
+.Sh DESCRIPTION
+This is another version of
+.Xr deflateInit 3
+with more compression options.
+The fields
+.Fa next_in ,
+.Fa zalloc ,
+.Fa zfree
+and
+.Fa opaque
+must be initialized before by the caller.
+.
+.Pp
+The
+.Fa method
+parameter is the compression method.
+It must be
+.Dv Z_DEFLATED
+in this version of the library.
+.
+.Pp
+The
+.Fa windowBits
+parameter is the base two logarithm
+of the window size
+(the size of the history buffer).
+It should be in the range 8..15
+for this version of the library.
+Larger values of this parameter
+result in better compression
+at the expense of memory usage.
+The default value is 15 if
+.Xr deflateInit 3
+is used instead.
+.
+.Pp
+For the current implementation of
+.Xr deflate 3 ,
+a
+.Fa windowBits
+value of 8
+(a window size of 256 bytes)
+is not supported.
+As a result,
+a request for 8
+will result in 9
+(a 512-byte window).
+In that case,
+providing 8 to
+.Xr inflateInit2 3
+will result in an error
+when the zlib header with 9
+is checked against the initialization of
+.Xr inflate 3 .
+The remedy is to not use 8 with
+.Fn deflateInit2
+with this initialization,
+or at least in that case use 9 with
+.Xr inflateInit2 3 .
+.
+.Pp
+.Fa windowBits
+can also be -8..-15 for raw deflate.
+In this case,
+.Fa -windowBits
+determines the window size.
+.Xr deflate 3
+will then generate raw deflate data
+with no zlib header or trailer,
+and will not compute a check value.
+.
+.Pp
+.Fa windowBits
+can also be greater than 15
+for optional gzip encoding.
+Add 16 to
+.Fa windowBits
+to write a simple gzip header and trailer
+around the compressed data
+instead of a zlib wrapper.
+The gzip header will have
+no file name,
+no extra data,
+no comment,
+no modification time (set to zero),
+no header CRC,
+and the operating system will be set
+to the appropriate value,
+if the operating system was determined at compile time.
+If a gzip stream is being written,
+.Fa strm->adler
+is a CRC-32 instead of an Adler-32.
+.
+.Pp
+For raw deflate or gzip encoding,
+a request for a 256-byte window
+is rejected as invalid,
+since only the zlib header provides
+a means of transmitting the window size
+to the decompressor.
+.
+.Pp
+The
+.Fa memLevel
+parameter specifies how much memory should be allocated
+for the internal compression state.
+.Fa memLevel=1
+uses minimum memory
+but is slow and reduces compression ratio;
+.Fa memLevel=9
+uses maximum memory for optimal speed.
+The default value is 8.
+See
+.In zconf.h
+for total memory usage
+as a function of
+.Fa windowBits
+and
+.Fa memLevel .
+.
+.Pp
+The
+.Fa strategy
+parameter is used to tune the compression algorithm.
+Use the value
+.Dv Z_DEFAULT_STRATEGY
+for normal data,
+.Dv Z_FILTERED
+for data produced by a filter
+(or predictor),
+.Dv Z_HUFFMAN_ONLY
+to force Huffman encoding only
+(no string match),
+or
+.Dv Z_RLE
+to limit match distances to one
+(run-length encoding).
+Filtered data consists mostly of small values
+with a somewhat random distribution.
+In this case,
+the compression algorithm
+is tuned to compress them better.
+The effect of
+.Dv Z_FILTERED
+is to force more Huffman coding
+and less string matching;
+it is somewhat intermediate between
+.Dv Z_DEFAULT_STRATEGY
+and
+.Dv Z_HUFFMAN_ONLY .
+.Dv Z_RLE
+is designed to be almost as fast as
+.Dv Z_HUFFMAN_ONLY ,
+but give better compression for PNG image data.
+The
+.Fa strategy
+parameter only affects the compression ratio
+but not the correctness of the compressed output
+even if it is not set appropriately.
+.Dv Z_FIXED
+prevents the use of dynamic Huffman codes,
+allowing for a simpler decoder
+for special applications.
+.
+.Pp
+.Fn deflateInit2
+does not perform any compression:
+this will be done by
+.Xr deflate 3 .
+.
+.Sh RETURN VALUES
+.Fn deflateInit2
+returns
+.Dv Z_OK
+if success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_STREAM_ERROR
+if any parameter is invalid
+(such as invalid method),
+or
+.Dv Z_VERSION_ERROR
+if the zlib library version
+.Pq Xr zlibVersion 3
+is incompatible with the version assumed by the caller
+.Pq Dv ZLIB_VERSION .
+.Fa msg
+is set to null if there is no error message.
+.
+.Sh SEE ALSO
+.Xr deflate 3 ,
+.Xr deflateInit 3 ,
+.Xr deflateParams 3 ,
+.Xr deflateSetHeader 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateParams.3 b/doc/zlib/deflateParams.3
new file mode 100644
index 00000000..9eb5ca16
--- /dev/null
+++ b/doc/zlib/deflateParams.3
@@ -0,0 +1,123 @@
+.Dd January 15, 2017
+.Dt DEFLATEPARAMS 3
+.Os
+.
+.Sh NAME
+.Nm deflateParams
+.Nd update compression level and strategy
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn deflateParams "z_streamp strm" "int level" "int strategy"
+.
+.Sh DESCRIPTION
+Dynamically update the compression level
+and compression strategy.
+The interpretation of
+.Fa level
+and
+.Fa strategy
+is as in
+.Xr deflateInit2 3 .
+This can be used to switch between compression
+and straight copy of the input data,
+or to switch to a different kind of input data
+requiring a different strategy.
+If the compression approach
+(which is a function of the level)
+or the strategy is changed,
+and if any input has been consumed
+in a previous
+.Xr deflate 3
+call,
+then the input available so far is compressed
+with the old level and strategy using
+.Fn deflate strm Z_BLOCK .
+There are three approaches
+for the compression levels
+0, 1..3, and 4..9 respectively.
+The new level and strategy
+will take effect at the next call of
+.Xr deflate 3 .
+.
+.Pp
+If a
+.Fn deflate strm Z_BLOCK
+is performed by
+.Fn deflateParams ,
+and it does not have enough output space to complete,
+then the parameter change will not take effect.
+In this case,
+.Fn deflateParams
+can be called again
+with the same parameters
+and more output space
+to try again.
+.
+.Pp
+In order to assure a change in the parameters
+on the first try,
+the deflate stream should be flushed using
+.Xr deflate 3
+with
+.Dv Z_BLOCK
+or other flush request until
+.Fa strm.avail_out
+is not zero,
+before calling
+.Fn deflateParams .
+Then no more input data
+should be provided before the
+.Fn deflateParams
+call.
+If this is done,
+the old level and strategy
+will be applied
+to the data compressed before
+.Fn deflateParams ,
+and the new level and strategy
+will be applied
+to the data compressed after
+.Fn deflateParams .
+.
+.Sh RETURN VALUES
+.Fn deflateParams
+returns
+.Dv Z_OK
+on success,
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent
+or if a parameter was invalid,
+or
+.Dv Z_BUF_ERROR
+if there was not enough output space
+to complete the compression
+of the available input data
+before a change in the strategy or approach.
+Note that in the case of a
+.Dv Z_BUF_ERROR ,
+the parameters are not changed.
+A return value of
+.Dv Z_BUF_ERROR
+is not fatal,
+in which case
+.Fn deflateParams
+can be retried
+with more output space.
+.
+.Sh SEE ALSO
+.Xr deflateInit2 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflatePending.3 b/doc/zlib/deflatePending.3
new file mode 100644
index 00000000..35fa6d38
--- /dev/null
+++ b/doc/zlib/deflatePending.3
@@ -0,0 +1,56 @@
+.Dd January 15, 2017
+.Dt DEFLATEPENDING 3
+.Os
+.
+.Sh NAME
+.Nm deflatePending
+.Nd pending deflate output
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn deflatePending "z_streamp strm" "unsigned *pending" "int *bits"
+.
+.Sh DESCRIPTION
+.Fn deflatePending
+returns the number of bytes and bits
+of output that have been generated,
+but not yet provided in the available output.
+The bytes not provided would be due to
+the available output space having been consumed.
+The number of bits of output not provided
+are between 0 and 7,
+where they await more bits to join them
+in order to fill out a full byte.
+If
+.Fa pending
+or
+.Fa bits
+are
+.Dv Z_NULL ,
+then those values are not set.
+.
+.Sh RETURN VALUES
+.Fn deflatePending
+returns
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr deflate 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflatePrime.3 b/doc/zlib/deflatePrime.3
new file mode 100644
index 00000000..10a2924b
--- /dev/null
+++ b/doc/zlib/deflatePrime.3
@@ -0,0 +1,64 @@
+.Dd January 15, 2017
+.Dt DEFLATEPRIME 3
+.Os
+.
+.Sh NAME
+.Nm deflatePrime
+.Nd insert bits in deflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn deflatePrime "z_streamp strm" "int bits" "int value"
+.
+.Sh DESCRIPTION
+.Fn deflatePrime
+inserts bits in the deflate output stream.
+The intent is that this function
+is used to start off the deflate output
+with the bits leftover
+from a previous deflate stream
+when appending to it.
+As such,
+this function can only be used for raw deflate,
+and must be used before the first
+.Xr deflate 3
+call
+after a
+.Xr deflateInit2 3
+or
+.Xr deflateReset 3 .
+.Fa bits
+must be less than or equal to 16,
+and that many of the least significant bits of
+.Fa value
+will be inserted in the output.
+.
+.Sh RETURN VALUES
+.Fn deflatePrime
+returns
+.Dv Z_OK
+if success,
+.Dv Z_BUF_ERROR
+if there was not enough room
+in the internal buffer
+to insert the bits,
+or
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr deflateInit2 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateReset.3 b/doc/zlib/deflateReset.3
new file mode 100644
index 00000000..1a18c507
--- /dev/null
+++ b/doc/zlib/deflateReset.3
@@ -0,0 +1,57 @@
+.Dd January 15, 2017
+.Dt DEFLATERESET 3
+.Os
+.
+.Sh NAME
+.Nm deflateReset
+.Nd reset deflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn deflateReset "z_streamp strm"
+.
+.Sh DESCRIPTION
+This function is equivalent to
+.Xr deflateEnd 3
+followed by
+.Xr deflateInit 3 ,
+but does not free and reallocate
+the internal compression state.
+The stream will leave the compression level
+and any other attributes
+that may have been set unchanged.
+.
+.Sh RETURN VALUES
+.Fn deflateReset
+returns
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent
+.Po
+such as
+.Fa zalloc
+or
+.Fa state
+being
+.Dv Z_NULL
+.Pc .
+.
+.Sh SEE ALSO
+.Xr deflateEnd 3 ,
+.Xr deflateInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateSetDictionary.3 b/doc/zlib/deflateSetDictionary.3
new file mode 100644
index 00000000..3e66d3cf
--- /dev/null
+++ b/doc/zlib/deflateSetDictionary.3
@@ -0,0 +1,142 @@
+.Dd January 15, 2017
+.Dt DEFLATESETDICTIONARY 3
+.Os
+.
+.Sh NAME
+.Nm deflateSetDictionary
+.Nd initialize compression dictionary
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fo deflateSetDictionary
+.Fa "z_streamp strm"
+.Fa "const Bytef *dictionary"
+.Fa "uInt dictLength"
+.Fc
+.
+.Sh DESCRIPTION
+.Fn deflateSetDictionary
+initializes the compression dictionary
+from the given byte sequence
+without producing any compressed output.
+When using the zlib format,
+this function must be called immediately after
+.Xr deflateInit 3 ,
+.Xr deflateInit2 3 ,
+or
+.Xr deflateReset 3 ,
+and before any call of
+.Xr deflate 3 .
+When doing raw deflate,
+this function must be called
+either before any call of
+.Xr deflate 3 ,
+or immediately after the completion of a deflate block,
+i.e. after all input has been consumed
+and all output has been delivered
+when using any of the flush options
+.Dv Z_BLOCK ,
+.Dv Z_PARTIAL_FLUSH ,
+.Dv Z_SYNC_FLUSH ,
+or
+.Dv Z_FULL_FLUSH .
+The compressor and decompressor
+must use exactly the same dictionary
+.Po
+see
+.Xr inflateSetDictionary 3
+.Pc .
+.
+.Pp
+The dictionary should consist of strings
+(byte sequences)
+that are likely to be encountered later
+in the data to be compressed,
+with the most commonly used strings
+preferably put towards the end of the dictionary.
+Using a dictionary is most useful
+when the data to be compressed is short
+and can be predicted with good accuracy;
+the data can then be compressed better than
+with the default empty dictionary.
+.
+.Pp
+Depending on the size of
+the compression data structures selected by
+.Xr deflateInit 3
+or
+.Xr deflateInit2 3 ,
+a part of the dictionary may in effect be discarded,
+for example if the dictionary is larger
+than the window size provided in
+.Xr deflateInit 3
+or
+.Xr deflateInit2 3 .
+Thus the strings most likely to be useful
+should be put at the end of the dictionary,
+not at the front.
+In addition,
+the current implementation of deflate
+will use at most the window size minus 262 bytes
+of the provided dictionary.
+.
+.Pp
+Upon return of this function,
+.Fa strm->adler
+is set to the Adler-32 value
+of the dictionary;
+the decompressor may later use this value
+to determine which dictionary has been used
+by the compressor.
+(The Adler-32 value applies to the whole dictionary
+even if only a subset of the dictionary
+is actually used by the compressor.)
+If a raw deflate was requested,
+then the Adler-32 value is not computed and
+.Fa strm->adler
+is not set.
+.
+.Pp
+.Fn deflateSetDictionary
+does not perform any compression:
+this will be done by
+.Xr deflate 3 .
+.
+.Sh RETURN VALUES
+.Fn deflateSetDictionary
+returns
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if a parameter is invalid
+.Po
+e.g. dictionary being
+.Dv Z_NULL
+.Pc
+or the stream state is inconsistent
+.Po
+for example if
+.Xr deflate 3
+has already been called for this stream
+or if not at a block boundary
+for raw deflate
+.Pc .
+.
+.Sh SEE ALSO
+.Xr deflateGetDictionary 3 ,
+.Xr inflateSetDictionary 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateSetHeader.3 b/doc/zlib/deflateSetHeader.3
new file mode 100644
index 00000000..03d4f4d3
--- /dev/null
+++ b/doc/zlib/deflateSetHeader.3
@@ -0,0 +1,180 @@
+.Dd January 15, 2017
+.Dt DEFLATESETHEADER 3
+.Os
+.
+.Sh NAME
+.Nm deflateSetHeader
+.Nd set gzip header
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.
+.Bd -literal
+typedef struct gz_header_s {
+	int     text;
+	uLong   time;
+	int     xflags;
+	int     os;
+	Bytef   *extra;
+	uInt    extra_len;
+	uInt    extra_max;
+	Bytef   *name;
+	uInt    name_max;
+	Bytef   *comment;
+	uInt    comm_max;
+	int     hcrc;
+	int     done;
+} gz_header;
+.Ed
+.
+.Pp
+.Vt typedef gz_header FAR *gz_headerp;
+.
+.Ft int
+.Fn deflateSetHeader "z_streamp strm" "gz_headerp head"
+.
+.Sh DESCRIPTION
+.Fn deflateSetHeader
+provides gzip header information
+for when a gzip stream
+is requested by
+.Xr deflateInit2 3 .
+.Fn deflateSetHeader
+may be called after
+.Xr deflateInit2 3
+or
+.Xr deflateReset 3
+and before the first call of
+.Xr deflate 3 .
+The
+text,
+time,
+OS,
+extra field,
+name,
+and comment
+information in the provided
+.Vt gz_header
+structure
+are written to the gzip header
+.Po
+.Fa xflag
+is ignored \(em
+the extra flags are set
+according to the compression level
+.Pc .
+The caller must assure that,
+if not
+.Dv Z_NULL ,
+.Fa name
+and
+.Fa comment
+are terminated with a zero byte,
+and that if
+.Fa extra
+is not
+.Dv Z_NULL ,
+that
+.Fa extra_len
+bytes are available there.
+If
+.Fa hcrc
+is true,
+a gzip header CRC is included.
+Note that the current versions
+of the command-line version of
+.Xr gzip 1
+(up through version 1.3.x)
+do not support header CRCs,
+and will report that it is a
+"multi-part gzip file"
+and give up.
+.
+.Pp
+If
+.Fn deflateSetHeader
+is not used,
+the default gzip header has
+text false,
+the time set to zero,
+and OS set to 255,
+with no extra, name, or comment fields.
+The gzip header is returned
+to the default state by
+.Xr deflateReset 3 .
+.
+.Pp
+The fields of
+.Vt gz_header
+are as follows:
+.
+.Bl -tag -width "extra_len"
+.It Fa text
+true if compressed data believed to be text
+.It Fa time
+modification time
+.It Fa xflags
+extra flags
+(not used when writing a gzip file)
+.It Fa os
+operating system
+.It Fa extra
+pointer to extra field or
+.Dv Z_NULL
+if none
+.It Fa extra_len
+extra field length
+.Po
+valid if
+.Fa extra
+!=
+.Dv Z_NULL
+.Pc
+.It Fa extra_max
+space at extra
+(only when reading header)
+.It Fa name
+pointer to zero-terminated file name or
+.Dv Z_NULL
+.It Fa name_max
+space at
+.Fa name
+(only when reading header)
+.It Fa comment
+pointer to zero-terminated comment or
+.Dv Z_NULL
+.It Fa comm_max
+space at comment
+(only when reading header)
+.It Fa hcrc
+true if there was or will be a header CRC
+.It Fa done
+true when done reading gzip header
+(not used when writing a gzip file)
+.El
+.
+.Sh RETURN VALUES
+.Fn deflateSetHeader
+returns
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr gzip 1 ,
+.Xr deflateInit2 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/deflateTune.3 b/doc/zlib/deflateTune.3
new file mode 100644
index 00000000..ea4dd915
--- /dev/null
+++ b/doc/zlib/deflateTune.3
@@ -0,0 +1,70 @@
+.Dd January 15, 2017
+.Dt DEFLATETUNE 3
+.Os
+.
+.Sh NAME
+.Nm deflateTune
+.Nd fine tune compression parameters
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fo deflateTune
+.Fa "z_streamp strm"
+.Fa "int good_length"
+.Fa "int max_lazy"
+.Fa "int nice_length"
+.Fa "int max_chain"
+.Fc
+.
+.Sh DESCRIPTION
+Fine tune deflate's internal compression parameters.
+This should only be used
+by someone who understands the algorithm
+used by zlib's deflate
+for searching for the best matching string,
+and even then only by the most fanatic optimizer
+trying to squeeze out the last compressed bit
+for their specific input data.
+Read the
+.Pa deflate.c
+source code for the meaning of the
+.Fa max_lazy ,
+.Fa good_length ,
+.Fa nice_length ,
+and
+.Fa max_chain
+parameters.
+.
+.Pp
+.Fn deflateTune
+can be called after
+.Xr deflateInit 3
+or
+.Xr deflateInit2 3 .
+.
+.Sh RETURN VALUES
+.Fn deflateTune
+returns
+.Dv Z_OK
+on success,
+or
+.Dv Z_STREAM_ERROR
+for an invalid deflate stream.
+.
+.Sh SEE ALSO
+.Xr deflateInit 3 ,
+.Xr deflateInit2 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzbuffer.3 b/doc/zlib/gzbuffer.3
new file mode 100644
index 00000000..92438c48
--- /dev/null
+++ b/doc/zlib/gzbuffer.3
@@ -0,0 +1,59 @@
+.Dd January 15, 2017
+.Dt GZBUFFER 3
+.Os
+.
+.Sh NAME
+.Nm gzbuffer
+.Nd set buffer size
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzbuffer "gzFile file" "unsigned size"
+.
+.Sh DESCRIPTION
+Set the internal buffer size
+used by this library's functions.
+The default buffer size is 8192 bytes.
+This function must be called after
+.Xr gzopen 3
+or
+.Xr gzdopen 3 ,
+and before any other calls
+that read or write the file.
+The buffer memory allocation
+is always deferred to the first read or write.
+Three times that size in buffer space is allocated.
+A larger buffer size of,
+for example,
+64K or 128K bytes
+will noticeably increase the speed
+of decompression (reading).
+.
+.Pp
+The new buffer size also affects
+the maximum length for
+.Xr gzprintf 3 .
+.
+.Sh RETURN VALUES
+.Fn gzbuffer
+returns 0 on success,
+or -1 on failure,
+such as being called too late.
+.
+.Sh SEE ALSO
+.Xr gzopen 3 ,
+.Xr gzprintf 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzclose.3 b/doc/zlib/gzclose.3
new file mode 100644
index 00000000..bfcc583e
--- /dev/null
+++ b/doc/zlib/gzclose.3
@@ -0,0 +1,97 @@
+.Dd January 15, 2017
+.Dt GZCLOSE 3
+.Os
+.
+.Sh NAME
+.Nm gzclose ,
+.Nm gzclose_r ,
+.Nm gzclose_w
+.Nd close compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzclose "gzFile file"
+.Ft int
+.Fn gzclose_r "gzFile file"
+.Ft int
+.Fn gzclose_w "gzFile file"
+.
+.Sh DESCRIPTION
+Flushes all pending output if necessary,
+closes the compressed file
+and deallocates the (de)compression state.
+Note that once
+.Fa file
+is closed,
+you cannot call
+.Xr gzerror 3
+with
+.Fa file ,
+since its structures
+have been deallocated.
+.Fn gzclose
+must not be called more than once
+on the same file,
+just as
+.Xr free 3
+must not be called more than once
+on the same allocation.
+.
+.Pp
+.Fn gzclose_r
+and
+.Fn gzclose_w
+are the same as
+.Fn gzclose ,
+but
+.Fn gzclose_r
+is only for use when reading,
+and
+.Fn gzclose_w
+is only for use when writing or appending.
+The advantage to using these instead of
+.Fn gzclose
+is that they avoid linking in
+zlib compression or decompression code
+that is not used when only reading
+or only writing respectively.
+If
+.Fn gzclose
+is used,
+then both compression and decompression code
+will be included in the application
+when linking to a static zlib library.
+.
+.Sh RETURN VALUES
+.Fn gzclose
+will return
+.Dv Z_STREAM_ERROR
+if
+.Fa file
+is not valid,
+.Dv Z_ERRNO
+on a file operator error,
+.Dv Z_MEM_ERROR
+if out of memory,
+.Dv Z_BUF_ERROR
+if the last read ended in the middle of a gzip stream,
+or
+.Dv Z_OK
+on success.
+.
+.Sh SEE ALSO
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzdirect.3 b/doc/zlib/gzdirect.3
new file mode 100644
index 00000000..640fd4c5
--- /dev/null
+++ b/doc/zlib/gzdirect.3
@@ -0,0 +1,85 @@
+.Dd January 15, 2017
+.Dt GZDIRECT 3
+.Os
+.
+.Sh NAME
+.Nm gzdirect
+.Nd check direct copy
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzdirect "gzFile file"
+.
+.Sh DESCRIPTION
+Returns true (1) if
+.Fa file
+is being copied directly while reading,
+or false (0) if
+.Fa file
+is a gzip stream being decompressed.
+.
+.Pp
+If the input file is empty,
+.Fn gzdirect
+will return true,
+since the input does not contain a gzip stream.
+.
+.Pp
+If
+.Fn gzdirect
+is used immediately after
+.Xr gzopen 3
+or
+.Xr gzdopen 3
+it will cause buffers to be allocated
+to allow reading the file
+to determine if it is a gzip file.
+Therefore if
+.Xr gzbuffer 3
+is used,
+it should be called before
+.Fn gzdirect .
+.
+.Pp
+When writing,
+.Fn gzdirect
+returns true (1)
+if transparent writing was requested
+.Po
+.Dq wT
+for the
+.Xr gzopen 3
+mode
+.Pc ,
+or false (0) otherwise.
+.Po
+Note:
+.Fn gzdirect
+is not needed when writing.
+Transparent writing
+must be explicitly requested,
+so the application already knows the answer.
+When linking statically,
+using
+.Fn gzdirect
+will include all of the zlib code
+for gzip file reading and decompression,
+which may not be desired.
+.Pc
+.
+.Sh SEE ALSO
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzeof.3 b/doc/zlib/gzeof.3
new file mode 100644
index 00000000..ba823aa6
--- /dev/null
+++ b/doc/zlib/gzeof.3
@@ -0,0 +1,63 @@
+.Dd January 15, 2017
+.Dt GZEOF 3
+.Os
+.
+.Sh NAME
+.Nm gzeof
+.Nd check end-of-file indicator
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzeof "gzFile file"
+.
+.Sh DESCRIPTION
+Returns true (1)
+if the end-of-file indicator
+has been set while reading,
+false (0) otherwise.
+Note that the end-of-file indicator
+is set only if the read
+tried to go past the end of the input,
+but came up short.
+Therefore,
+just like
+.Xr feof 3 ,
+.Fn gzeof
+may return false
+even if there is no more data to read,
+in the event that the last read request
+was for the exact number of bytes
+remaining in the input file.
+This will happen if the input file size
+is an exact multiple of the buffer size.
+.
+.Pp
+If
+.Fn gzeof
+returns true,
+then the read functions
+will return no more data,
+unless the end-of-file indicator
+is reset by
+.Xr gzclearerr 3
+and the input file
+has grown since the previous
+end of file was detected.
+.
+.Sh SEE ALSO
+.Xr gzerror 3 ,
+.Xr gzread 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzerror.3 b/doc/zlib/gzerror.3
new file mode 100644
index 00000000..a9e175fc
--- /dev/null
+++ b/doc/zlib/gzerror.3
@@ -0,0 +1,75 @@
+.Dd January 15, 2017
+.Dt GZERROR 3
+.Os
+.
+.Sh NAME
+.Nm gzerror ,
+.Nm gzclearerr
+.Nd check and reset compressed file error
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft const char *
+.Fn gzerror "gzFile file" "int *errnum"
+.Ft void
+.Fn gzclearerr "gzFile file"
+.
+.Sh DESCRIPTION
+.Fn gzerror
+returns the error message for the last error
+which occured on the given compressed file.
+.Fa errnum
+is set to the zlib error number.
+If an error occurred in the file system
+and not in the compression library,
+.Fa errnum
+is set to
+.Dv Z_ERRNO
+and the application may consult
+.Va errno
+to get the exact error code.
+.
+.Pp
+The application must not modify the returned string.
+Future calls to this function
+may invalidate the previously returned string.
+If
+.Fa file
+is closed,
+then the string previously returned by
+.Fn gzerror
+will no longer be available.
+.
+.Pp
+.Fn gzerror
+should be used to distinguish errors from end-of-file
+for those functions that do not distinguish those cases
+in their return values.
+.
+.Pp
+.Fn gzclearerr
+clears the error and end-of-file for
+.Fa file .
+This is analogous to the
+.Xr clearerr 3
+function in stdio.
+This is useful for continuing to read a gzip file
+that is being written concurrently.
+.
+.Sh SEE ALSO
+.Xr gzeof 3 ,
+.Xr gzread 3 ,
+.Xr gzwrite 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzflush.3 b/doc/zlib/gzflush.3
new file mode 100644
index 00000000..476f7c09
--- /dev/null
+++ b/doc/zlib/gzflush.3
@@ -0,0 +1,73 @@
+.Dd January 15, 2017
+.Dt GZFLUSH 3
+.Os
+.
+.Sh NAME
+.Nm gzflush
+.Nd flush output to compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzflush "gzFile file" "int flush"
+.
+.Sh DESCRIPTION
+Flushes all pending output
+into the compressed file.
+The parameter
+.Fa flush
+is as in the
+.Xr deflate 3
+function.
+.Fn gzflush
+is only permitted when writing.
+.
+.Pp
+If the
+.Fa flush
+parameter is
+.Dv Z_FINISH ,
+the remaining data is written
+and the gzip stream
+is completed in the output.
+If
+.Xr gzwrite 3
+is called again,
+a new gzip stream
+will be started in the output.
+.Xr gzread 3
+is able to read
+such concatenated gzip streams.
+.
+.Pp
+.Fn gzflush
+should be called only when strictly necessary
+because it will degrade compression
+if called too often.
+.
+.Sh RETURN VALUES
+The return value
+is the zlib error number
+.Po
+see function
+.Xr gzerror 3
+.Pc .
+.
+.Sh SEE ALSO
+.Xr deflate 3 ,
+.Xr gzerror 3 ,
+.Xr gzread 3 ,
+.Xr gzwrite 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzfread.3 b/doc/zlib/gzfread.3
new file mode 100644
index 00000000..7bf57fc5
--- /dev/null
+++ b/doc/zlib/gzfread.3
@@ -0,0 +1,107 @@
+.Dd January 15, 2017
+.Dt GZFREAD 3
+.Os
+.
+.Sh NAME
+.Nm gzfread
+.Nd read from compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft z_size_t
+.Fn gzfread "voidp buf" "z_size_t size" "z_size_t nitems" "gzFile file"
+.
+.Sh DESCRIPTION
+Read up to
+.Fa nitems
+of size
+.Fa size
+from
+.Fa file
+to
+.Fa buf ,
+otherwise operating as
+.Xr gzread 3
+does.
+This duplicates the interface of stdio's
+.Xr fread 3 ,
+with
+.Vt size_t
+request and return types.
+If the library defines
+.Vt size_t ,
+then
+.Vt z_size_t
+is identical to
+.Vt size_t .
+If not,
+then
+.Vt z_size_t
+is an unsigned integer type
+that can contain a pointer.
+.
+.Pp
+In the event that the end of file is reached
+and only a partial item is available at the end,
+i.e. the remaining uncompressed data length
+is not a multiple of
+.Fa size ,
+then the file partial item
+is nevertheless read into
+.Fa buf
+and the end-of-file flag is set.
+The length of the partial item read
+is not provided,
+but could be inferred from the result of
+.Xr gztell 3 .
+This behavior is the same as the behavior of
+.Xr fread 3
+implementations in common libraries,
+but it prevents the direct use of
+.Fn gzfread
+to read a concurrently written file,
+reseting and retrying on end-of-file,
+when
+.Fa size
+is not 1.
+.
+.Sh RETURN VALUES
+.Fn gzfread
+returns the number of full items read of size
+.Fa size ,
+or zero if the end of the file was reached
+and a full item could not be read,
+or if there was an error.
+.Xr gzerror 3
+must be consulted if zero is returned
+in order to determine if there was an error.
+If the multiplication of
+.Fa size
+and
+.Fa nitems
+overflows,
+i.e. the product does not fit in
+.Vt z_size_t ,
+then nothing is read,
+zero is returned,
+and the error state is set to
+.Dv Z_STREAM_ERROR .
+.
+.Sh SEE ALSO
+.Xr gzeof 3 ,
+.Xr gzerror 3 ,
+.Xr gzopen 3 ,
+.Xr gzread 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzfwrite.3 b/doc/zlib/gzfwrite.3
new file mode 100644
index 00000000..6835db3a
--- /dev/null
+++ b/doc/zlib/gzfwrite.3
@@ -0,0 +1,75 @@
+.Dd January 15, 2017
+.Dt GZFWRITE 3
+.Os
+.
+.Sh NAME
+.Nm gzfwrite
+.Nd write to compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft z_size_t
+.Fn gzfwrite "voidpc buf" "z_size_t size" "z_size_t nitems" "gzFile file"
+.
+.Sh DESCRIPTION
+.Fn gzfwrite
+writes
+.Fa nitems
+items of size
+.Fa size
+from
+.Fa buf
+to
+.Fa file ,
+duplicating the interface of stdio's
+.Xr fwrite 3 ,
+with
+.Vt size_t
+request and return types.
+If the library defines
+.Vt size_t ,
+then
+.Vt z_size_t
+is identical to
+.Vt size_t .
+If not,
+then
+.Vt z_size_t
+is an unsigned integer type
+that can contain a pointer.
+.
+.Sh RETURN VALUES
+.Fn gzfwrite
+returns the number of full items
+written of size
+.Fa size ,
+or zero if there was an error.
+If the multiplication of
+.Fa size
+and
+.Fa nitems
+overflows,
+i.e. the product does not fit in a
+.Vt z_size_t ,
+then nothing is written,
+zero is returned,
+and the error state is set to
+.Dv Z_STREAM_ERROR .
+.
+.Sh SEE ALSO
+.Xr gzerror 3 ,
+.Xr gzopen 3 ,
+.Xr gzwrite 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzgetc.3 b/doc/zlib/gzgetc.3
new file mode 100644
index 00000000..db9143ec
--- /dev/null
+++ b/doc/zlib/gzgetc.3
@@ -0,0 +1,55 @@
+.Dd January 15, 2017
+.Dt GZGETC 3
+.Os
+.
+.Sh NAME
+.Nm gzgetc
+.Nd get character from compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzgetc "gzFile file"
+.
+.Sh DESCRIPTION
+Reads one byte from the compressed file.
+This is implemented as a macro for speed.
+As such,
+it does not do all of the checking
+the other functions do.
+I.e.\&
+it does not check to see if
+.Fa file
+is
+.Dv NULL ,
+nor whether the structure
+.Fa file
+points to has been clobbered or not.
+.
+.Sh RETURN VALUES
+.Fn gzgetc
+returns the byte
+or -1 in case of
+end of file
+or error.
+.
+.Sh SEE ALSO
+.Xr gzeof 3 ,
+.Xr gzerror 3 ,
+.Xr gzgets 3 ,
+.Xr gzopen 3 ,
+.Xr gzread 3 ,
+.Xr gzungetc 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzgets.3 b/doc/zlib/gzgets.3
new file mode 100644
index 00000000..c1435b39
--- /dev/null
+++ b/doc/zlib/gzgets.3
@@ -0,0 +1,67 @@
+.Dd January 15, 2017
+.Dt GZGETS 3
+.Os
+.
+.Sh NAME
+.Nm gzgets
+.Nd read line from compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft char *
+.Fn gzgets "gzFile file" "char *buf" "int len"
+.
+.Sh DESCRIPTION
+Reads bytes from the compressed file
+until
+.Fa len-1
+characters are read,
+or a newline character
+is read and transferred to
+.Fa buf ,
+or an end-of-file condition
+is encountered.
+If any characters are read or if
+.Fa len
+== 1,
+the string is terminated
+with a null character.
+If no characters are read
+due to an end-of-file or
+.Fa len
+< 1,
+then the buffer is left untouched.
+.
+.Sh RETURN VALUES
+.Fn gzgets
+returns
+.Fa buf
+which is a null-terminated string,
+or it returns
+.Dv NULL
+for end-of-file
+or in case of error.
+If there was an error,
+the contents at
+.Fa buf
+are indeterminate.
+.
+.Sh SEE ALSO
+.Xr gzeof 3 ,
+.Xr gzerror 3 ,
+.Xr gzgetc 3 ,
+.Xr gzopen 3 ,
+.Xr gzread 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzoffset.3 b/doc/zlib/gzoffset.3
new file mode 100644
index 00000000..b03c557e
--- /dev/null
+++ b/doc/zlib/gzoffset.3
@@ -0,0 +1,51 @@
+.Dd January 15, 2017
+.Dt GZOFFSET 3
+.Os
+.
+.Sh NAME
+.Nm gzoffset
+.Nd offset in compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft z_off_t
+.Fn gzoffset "gzFile file"
+.
+.Sh DESCRIPTION
+Returns the current offset
+in the file being read or written.
+This offset includes
+the count of bytes
+that precede the gzip stream,
+for example when appending
+or when using
+.Xr gzdopen 3
+for reading.
+When reading,
+the offset does not include
+as yet unused buffered input.
+This information can be used
+for a progress indicator.
+.
+.Sh RETURN VALUES
+On error,
+.Fn gzoffset
+returns -1.
+.
+.Sh SEE ALSO
+.Xr gzerror 3 ,
+.Xr gzopen 3 ,
+.Xr gzseek 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzopen.3 b/doc/zlib/gzopen.3
new file mode 100644
index 00000000..9da647e1
--- /dev/null
+++ b/doc/zlib/gzopen.3
@@ -0,0 +1,261 @@
+.Dd January 15, 2017
+.Dt GZOPEN 3
+.Os
+.
+.Sh NAME
+.Nm gzopen ,
+.Nm gzdopen
+.Nd open gzip file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft gzFile
+.Fn gzopen "const char *path" "const char *mode"
+.Ft gzFile
+.Fn gzdopen "int fd" "const char *mode"
+.
+.Sh DESCRIPTION
+Opens a gzip (.gz) file
+for reading or writing.
+The
+.Fa mode
+parameter is as in
+.Xr fopen 3
+.Po
+.Dq rb
+or
+.Dq wb
+.Pc
+but can also include a compression level
+.Pq Dq wb9
+or a strategy:
+.Sq f
+for filtered data as in
+.Dq wb6f ,
+.Sq h
+for Huffman-only compression as in
+.Dq wb1h ,
+.Sq R
+for run-length encoding as in
+.Dq wb1R ,
+or
+.Sq F
+for fixed code compression as in
+.Dq wb9F .
+.Po
+See the description of
+.Xr deflateInit2 3
+for more information about the
+.Fa strategy
+parameter.
+.Pc \&
+.Sq T
+will request transparent writing or appending
+with no compression
+and not using the gzip format.
+.
+.Pp
+.Dq a
+can be used instead of
+.Dq w
+to request that the gzip stream
+that will be written
+be appended to the file.
+.Dq +
+will result in an error,
+since reading and writing
+to the same gzip file
+is not supported.
+The addition of
+.Dq x
+when writing will create the file exclusively,
+which fails if the file already exists.
+On systems that support it,
+the addition of
+.Dq e
+when reading or writing
+will set the flag to close the file on an
+.Xr execve 2
+call.
+.
+.Pp
+These functions,
+as well as
+.Xr gzip 1 ,
+will read and decode
+a sequence of gzip streams in a file.
+The append function of
+.Fn gzopen
+can be used to create such a file.
+.Po
+Also see
+.Xr gzflush 3
+for another way to do this.
+.Pc \&
+When appending,
+.Fn gzopen
+does not test whether the file begins with a gzip stream,
+nor does it look for the end of the gzip streams
+to begin appending.
+.Fn gzopen
+will simply append a gzip stream
+to the existing file.
+.
+.Pp
+.Fn gzopen
+can be used to read a file which is not in gzip format;
+in this case
+.Xr gzread 3
+will directly read from the file without decompression.
+When reading,
+this will be detected automatically
+by looking for the magic two-byte gzip header.
+.
+.Pp
+.Fn gzdopen
+associates at
+.Vt gzFile
+with the file descriptor
+.Fa fd .
+File descriptors
+are obtained from calls like
+.Xr open 2 ,
+.Xr dup 2 ,
+.Xr creat 2 ,
+.Xr pipe 2
+or
+.Xr fileno 3
+.Po
+if the file has been previously opened with
+.Xr fopen 3
+.Pc .
+The
+.Fa mode
+parameter is as in
+.Fn gzopen .
+.
+.Pp
+The next call of
+.Xr gzclose 3
+on the returned
+.Vt gzFile
+will also close the file descriptor
+.Fa fd ,
+just like
+.Xr fclose 3 .
+If you want to keep
+.Fa fd
+open,
+use
+.Li "fd = dup(fd_keep); gz = gzdopen(fd, mode)" .
+The duplicated descriptor should be saved
+to avoid a leak,
+since
+.Fn gzdopen
+does not close
+.Fa fd
+if it fails.
+If you are using
+.Xr fileno 3
+to get the file descriptor from a
+.Vt FILE * ,
+then you will have to use
+.Xr dup 2
+to avoid double-closing
+the file descriptor.
+Both
+.Xr gzclose 3
+and
+.Xr flcose 3
+will close the associated file descriptor,
+so they need to have different file descriptors.
+.
+.Sh RETURN VALUES
+.Fn gzopen
+and
+.Fn gzdopen
+return
+.Dv NULL
+if the file could not be opened,
+if there was insufficient memory
+to allocate the
+.Vt gzFile
+state,
+or if an invalid
+.Fa mode
+was specified
+.Po
+an
+.Sq r ,
+.Sq w ,
+or
+.Sq a
+was not provided,
+or
+.Sq +
+was provided
+.Pc ,
+or if
+.Fa fd
+is -1.
+The file descriptor
+is not used until the next
+gz* read, write, seek, or close operation,
+so
+.Fn gzdopen
+will not detect if
+.Fa fd
+is invalid
+.Po
+unless
+.Fa fd
+is -1
+.Pc .
+.Va errno
+can be checked
+to determine if the reason
+.Fn gzopen
+failed was that the file
+could not be opened.
+.
+.Sh ERRORS
+The
+.Fn gzopen
+function may fail and set
+.Va errno
+for any of the errors specified
+for the routine
+.Xr fopen 3 .
+.
+.Sh SEE ALSO
+.Xr deflateInit2 3 ,
+.Xr fopen 3 ,
+.Xr gzbuffer 3 ,
+.Xr gzclose 3 ,
+.Xr gzdirect 3 ,
+.Xr gzeof 3 ,
+.Xr gzerror 3 ,
+.Xr gzflush 3 ,
+.Xr gzgetc 3 ,
+.Xr gzgets 3 ,
+.Xr gzoffset 3 ,
+.Xr gzprintf 3 ,
+.Xr gzputc 3 ,
+.Xr gzputs 3 ,
+.Xr gzread 3 ,
+.Xr gzseek 3 ,
+.Xr gzsetparams 3 ,
+.Xr gzwrite 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzprintf.3 b/doc/zlib/gzprintf.3
new file mode 100644
index 00000000..a2a241a2
--- /dev/null
+++ b/doc/zlib/gzprintf.3
@@ -0,0 +1,71 @@
+.Dd January 15, 2017
+.Dt GZPRINTF 3
+.Os
+.
+.Sh NAME
+.Nm gzprintf
+.Nd format output to compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzprintf "gzFile file" "const char *format" "..."
+.
+.Sh DESCRIPTION
+Converts, formats, and writes the arguments
+to the compressed file
+under control of the format string,
+as in
+.Xr fprintf 3 .
+.
+.Sh RETURN VALUES
+.Fn gzprintf
+returns the number of
+uncompressed bytes actually written,
+or a negative zlib error code
+in case of error.
+The number of uncompressed bytes written
+is limited to 8191,
+or one less than the buffer size given to
+.Xr gzbuffer 3 .
+The caller should assure that
+this limit is not exceeded.
+If it is exceeded,
+then
+.Fn gzprintf
+will return an error (0)
+with nothing written.
+In this case,
+there may also be a buffer overflow
+with unpredictable consequences,
+which is possibly only if zlib
+was compiled with the insecure functions
+.Xr sprintf 3
+or
+.Xr vsprintf 3
+because the secure
+.Xr snprintf 3
+or
+.Xr vsnprintf 3
+functions
+were not available.
+This can be determined using
+.Xr zlibCompileFlags 3 .
+.
+.Sh SEE ALSO
+.Xr fprintf 3 ,
+.Xr gzerror 3 ,
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzputc.3 b/doc/zlib/gzputc.3
new file mode 100644
index 00000000..66897b5e
--- /dev/null
+++ b/doc/zlib/gzputc.3
@@ -0,0 +1,43 @@
+.Dd January 15, 2017
+.Dt GZPUTC 3
+.Os
+.
+.Sh NAME
+.Nm gzputc
+.Nd write character to compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzputc "gzFile file" "int c"
+.
+.Sh DESCRIPTION
+Writes
+.Fa c ,
+converted to an
+.Vt unsigned char ,
+into the compressed file.
+.
+.Sh RETURN VALUES
+.Fn gzputc
+returns the value that was written,
+or -1 in case of error.
+.
+.Sh SEE ALSO
+.Xr gzerror 3 ,
+.Xr gzopen 3 ,
+.Xr gzputs 3 ,
+.Xr gzwrite 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzputs.3 b/doc/zlib/gzputs.3
new file mode 100644
index 00000000..71833ab2
--- /dev/null
+++ b/doc/zlib/gzputs.3
@@ -0,0 +1,41 @@
+.Dd January 15, 2017
+.Dt GZPUTS 3
+.Os
+.
+.Sh NAME
+.Nm gzputs
+.Nd write string to compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzputs "gzFile file" "const char *s"
+.
+.Sh DESCRIPTION
+Writes the given null-terminated string
+to the compressed file,
+excluding the terminating null character.
+.
+.Sh RETURN VALUES
+.Fn gzputs
+returns the number of characters written,
+or -1 in case of error.
+.
+.Sh SEE ALSO
+.Xr gzerror 3 ,
+.Xr gzopen 3 ,
+.Xr gzputc 3 ,
+.Xr gzwrite 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzread.3 b/doc/zlib/gzread.3
new file mode 100644
index 00000000..4118eca7
--- /dev/null
+++ b/doc/zlib/gzread.3
@@ -0,0 +1,115 @@
+.Dd January 15, 2017
+.Dt GZREAD 3
+.Os
+.
+.Sh NAME
+.Nm gzread
+.Nd read from compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzread "gzFile file" "voidp buf" "unsigned len"
+.
+.Sh DESCRIPTION
+Reads the given number of uncompressed bytes
+from the compressed file.
+If the input file
+is not in gzip format,
+.Fn gzread
+copies the given number of bytes
+into the buffer directly from the file.
+.
+.Pp
+After reaching the end of a gzip stream
+in the input,
+.Fn gzread
+will continue to read,
+looking for another gzip stream.
+Any number of gzip streams
+may be concatenated in the input file,
+and will all be decompressed by
+.Fn gzread .
+If something other than a gzip stream
+is encountered after a gzip stream,
+that remaining trailing garbage is ignored
+(and no error is returned).
+.
+.Pp
+.Fn gzread
+can be used to read a gzip file
+that is being concurrently written.
+Upon reaching the end of the input,
+.Fn gzread
+will return with the available data.
+If the error code returned by
+.Xr gzerror 3
+is
+.Dv Z_OK
+or
+.Dv Z_BUF_ERROR ,
+then
+.Xr gzclearerr 3
+can be used
+to clear the end of file indicator
+in order to permit
+.Fn gzread
+to be tried again.
+.Dv Z_OK
+indicates that a gzip stream was completed
+on the last
+.Fn gzread .
+.Dv Z_BUF_ERROR
+indicates that the input file
+ended in the middle of a gzip stream.
+Note that
+.Fn gzread
+does not return -1
+in the event of an incomplete gzip stream.
+This error is deferred until
+.Xr gzclose 3 ,
+which will return
+.Dv Z_BUF_ERROR
+if the last
+.Fn gzread
+ended in the middle of a gzip stream.
+Alternatively,
+.Xr gzerror 3
+can be used before
+.Xr gzclose 3
+to detect this case.
+.
+.Sh RETURN VALUES
+.Fn gzread
+returns the number of uncompressed bytes actually read,
+less than
+.Fa len
+for end of file,
+or -1 for error.
+If
+.Fa len
+is too large to fit in an
+.Vt int ,
+then nothing is read,
+-1 is returned,
+and the error state is set to
+.Dv Z_STREAM_ERROR .
+.
+.Sh SEE ALSO
+.Xr gzeof 3 ,
+.Xr gzerror 3 ,
+.Xr gzfread 3 ,
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzseek.3 b/doc/zlib/gzseek.3
new file mode 100644
index 00000000..a14b2db6
--- /dev/null
+++ b/doc/zlib/gzseek.3
@@ -0,0 +1,108 @@
+.Dd January 15, 2017
+.Dt GZSEEK 3
+.Os
+.
+.Sh NAME
+.Nm gzseek ,
+.Nm gzrewind ,
+.Nm gztell
+.Nd seek compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft z_off_t
+.Fn gzseek "gzFile file" "z_off_t offset" "int whence"
+.Ft int
+.Fn gzrewind "gzFile file"
+.Ft z_off_t
+.Fn gztell "gzFile file"
+.
+.Sh DESCRIPTION
+Sets the starting position
+for the next
+.Xr gzread 3
+or
+.Xr gzwrite 3
+on the given compressed file.
+The
+.Fa offset
+represents a number of bytes
+in the uncompressed data stream.
+The
+.Fa whence
+parameter
+is defined as in
+.Xr lseek 2 ;
+the value
+.Dv SEEK_END
+is not supported.
+.
+.Pp
+If the file is opened for reading,
+this function is emulated
+but can be extremely slow.
+If the file is opened for writing,
+only forward seeks are supported;
+.Fn gzseek
+then compresses a sequence of zeroes
+up to the new starting position.
+.
+.Pp
+.Fn gzrewind
+rewinds the given file.
+This function is supported
+only for reading.
+.
+.Pp
+.Fn gzrewind file
+is equivalent to
+.Li (int) Ns Fn gzseek file 0L SEEK_SET .
+.
+.Pp
+.Fn gztell
+returns the starting position
+for the next
+.Xr gzread 3
+or
+.Xr gzwrite 3
+on the given compressed file.
+This position represents a number of bytes
+in the uncompressed data stream,
+and is zero when starting,
+even if appending or reading
+a gzip stream from the middle of a file using
+.Xr gzdopen 3 .
+.
+.Pp
+.Fn gztell file
+is equivalent to
+.Fn gzseek file 0L SEEK_CUR .
+.
+.Sh RETURN VALUES
+.Fn gzseek
+returns the resulting offset location
+as measured in bytes
+from the beginning of the uncompressed stream,
+or -1 in case of error,
+in particular if the file
+is opened for writing
+and the new starting position
+would be before the current position.
+.
+.Sh SEE ALSO
+.Xr gzerror 3 ,
+.Xr gzoffset 3 ,
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzsetparams.3 b/doc/zlib/gzsetparams.3
new file mode 100644
index 00000000..f6ff9ed7
--- /dev/null
+++ b/doc/zlib/gzsetparams.3
@@ -0,0 +1,51 @@
+.Dd January 15, 2017
+.Dt GZSETPARAMS 3
+.Os
+.
+.Sh NAME
+.Nm gzsetparams
+.Nd set compression level and strategy
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzsetparams "gzFile file" "int level" "int strategy"
+.
+.Sh DESCRIPTION
+Dynamically update the compression level or strategy.
+See the description of
+.Xr deflateInit2 3
+for the meaning
+of these parameters.
+Previously provided data is flushed
+before the parameter change.
+.
+.Sh RETURN VALUES
+.Fn gzsetparams
+returns
+.Dv Z_OK
+if success,
+.Dv Z_STREAM_ERROR
+if the file was not opened for writing,
+.Dv Z_ERRNO
+if there is an error writing the flushed data,
+or
+.Dv Z_MEM_ERROR
+if there is a memory allocation error.
+.
+.Sh SEE ALSO
+.Xr deflateInit2 3 ,
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzungetc.3 b/doc/zlib/gzungetc.3
new file mode 100644
index 00000000..fbe9371c
--- /dev/null
+++ b/doc/zlib/gzungetc.3
@@ -0,0 +1,67 @@
+.Dd January 15, 2017
+.Dt GZUNGETC 3
+.Os
+.
+.Sh NAME
+.Nm gzungetc
+.Nd un-get character from compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzungetc "int c" "gzFile file"
+.
+.Sh DESCRIPTION
+Push one character back onto the stream
+to be read as the first character
+on the next read.
+At least one character of push-back
+is allowed.
+.Fn gzungetc
+will fail if
+.Fa c
+is -1,
+and may fail if a character
+has been pushed
+but not read yet.
+If
+.Fn gzungetc
+is used immediately after
+.Xr gzopen 3
+or
+.Xr gzdopen 3 ,
+at least the output buffer size
+of pushed characters is allowed.
+.Po
+See
+.Xr gzbuffer 3 .
+.Pc \&
+The pushed character will be discarded
+if the stream is repositioned with
+.Xr gzseek 3
+or
+.Xr gzrewind 3 .
+.
+.Sh RETURN VALUES
+.Fn gzungetc
+returns the character pushed,
+or -1 on failure.
+.
+.Sh SEE ALSO
+.Xr gzbuffer 3 ,
+.Xr gzerror 3 ,
+.Xr gzgetc 3 ,
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/gzwrite.3 b/doc/zlib/gzwrite.3
new file mode 100644
index 00000000..73407ef5
--- /dev/null
+++ b/doc/zlib/gzwrite.3
@@ -0,0 +1,39 @@
+.Dd January 15, 2017
+.Dt GZWRITE 3
+.Os
+.
+.Sh NAME
+.Nm gzwrite
+.Nd write to compressed file
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn gzwrite "gzFile file" "voidpc buf" "unsigned len"
+.
+.Sh DESCRIPTION
+Writes the given number of uncompressed bytes
+into the compressed file.
+.
+.Sh RETURN VALUES
+.Fn gzwrite
+returns the number of uncompressed bytes written
+or 0 in case of error.
+.
+.Sh SEE ALSO
+.Xr gzerror 3 ,
+.Xr gzfwrite 3 ,
+.Xr gzopen 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflate.3 b/doc/zlib/inflate.3
new file mode 100644
index 00000000..255e0f84
--- /dev/null
+++ b/doc/zlib/inflate.3
@@ -0,0 +1,398 @@
+.Dd January 15, 2017
+.Dt INFLATE 3
+.Os
+.
+.Sh NAME
+.Nm inflate
+.Nd deflate decompression
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflate "z_streamp strm" "int flush"
+.
+.Sh DESCRIPTION
+.Fn inflate
+decompresses as much data as possible,
+and stops when the input buffer becomes empty
+or the output buffer becomes full.
+It may introduce some output latency
+(reading input without producing any output)
+except when forced to flush.
+.
+.Pp
+The detailed semantics are as follows.
+.Fn inflate
+performs one or both of the following actions:
+.
+.Bl -dash
+.It
+Decompress more input starting at
+.Fa next_in
+and update
+.Fa next_in
+and
+.Fa avail_in
+accordingly.
+If not all input can be processed
+(because there is not enough room in the output buffer),
+then
+.Fa next_in
+and
+.Fa avail_in
+are updated accordingly,
+and processing will resume at this point
+for the next call of
+.Fn inflate .
+.
+.It
+Generate more output starting at
+.Fa next_out
+and update
+.Fa next_out
+and
+.Fa avail_out
+accordingly.
+.Fn inflate
+provides as much output as possible,
+until there is no more input data
+or no more space in the output buffer
+.Po
+see below about the
+.Fa flush
+parameter
+.Pc .
+.El
+.
+.Pp
+Before the call of
+.Fn inflate ,
+the application should ensure that
+at least one of the actions is possible,
+by providing more input
+and/or consuming more output,
+and updating the
+.Fa next_*
+and
+.Fa avail_*
+values accordingly.
+If the caller of
+.Fn inflate
+does not provide both available input
+and available output space,
+it is possible that there will be no progress made.
+The application can consume the uncompressed output
+when it wants,
+for example when the output buffer is full
+.Po
+.Fa avail_out
+== 0
+.Pc ,
+or after each call of
+.Fn inflate .
+If
+.Fn inflate
+returns
+.Dv Z_OK
+and with zero
+.Fa avail)out ,
+it must be called again after making room
+in the output buffer
+because there might be more output pending.
+.
+.Pp
+The
+.Fa flush
+parameter of
+.Fn inflate
+can be
+.Dv Z_NO_FLUSH ,
+.Dv Z_SYNC_FLUSH ,
+.Dv Z_FINISH ,
+.Dv Z_BLOCK ,
+or
+.Dv Z_TREES .
+.Dv Z_SYNC_FLUSH
+requests that
+.Fn inflate
+flush as much output as possible
+to the output buffer.
+.Dv Z_BLOCK
+requests that
+.Fn inflate
+stop if and when it gets to the next deflate block boundary.
+When decoding the zlib or gzip format,
+this will cause
+.Fn inflate
+to return immediately after the header
+and before the first block.
+When doing a raw inflate,
+.Fn inflate
+will go ahead and process the first block,
+and will return when it gets to the end of that block,
+or when it runs out of data.
+.
+.Pp
+The
+.Dv Z_BLOCK
+option assists in appending to
+or combining deflate streams.
+To assist in this,
+on return
+.Fn inflate
+always sets
+.Fa strm->data_type
+to the number of unused bits
+in the last byte taken from
+.Fa strm->next_in ,
+plus 64 if
+.Fn inflate
+is currently decoding the last block in the deflate stream,
+plus 128 if
+.Fn inflate
+returned immediately after decoding an end-of-block code
+or decoding the complete header up to
+just before the first byte of the deflate stream.
+The end-of-block will not be indicated
+until all of the uncompressed data
+from that block has been written to
+.Fa strm->next_out .
+The number of unused bits may in general be greater than seven,
+except when bit 7 of
+.Fa data_type
+is set,
+in which case the number of unused bits
+will be less than eight.
+.Fa data_type
+is set as noted here every time
+.Fn inflate
+returns for all flush options,
+and so can be used to determine
+the amount of currently consumed input in bits.
+.
+.Pp
+The
+.Dv Z_TREES
+option behaves as
+.Dv Z_BLOCK
+does,
+but it also returns
+when the end of each deflate block header is reached,
+before any actual data in that block is decoded.
+This allows the caller to determine
+the length of the deflate block header
+for later use in random access
+within a deflate block.
+256 is added to the value of
+.Fa strm->data_type
+when
+.Fn inflate
+returns immediately after reaching
+the end of the deflate block header.
+.
+.Pp
+.Fn inflate
+should normally be called until it returns
+.Dv Z_STREAM_END
+or an error.
+However if all decompression is to be performed
+in a single step
+.Po
+a single call of
+.Fn inflate
+.Pc ,
+the parameter
+.Fa flush
+should be set to
+.Dv Z_FINISH .
+In this case all pending input is processed
+and all pending output is flushed;
+.Fa avail_out
+must be large enough to hold all of
+the uncompressed data for the operation to complete.
+(The size of the uncompressed data
+may have been saved by the compressor for this purpose.)
+The use of
+.Dv Z_FINISH
+is not required to perform inflation in one step.
+However it may be used to inform
+.Fn inflate
+that a faster approach can be used for the single
+.Fn inflate
+call.
+.Dv Z_FINISH also informs
+.Fn inflate
+to not maintain a sliding window
+if the stream completes,
+which reduces
+.Fn inflate Ap s
+memory footprint.
+If the stream does not complete,
+either because not all of the stream is provided
+or not enough output space is provided,
+then a sliding window will be allocated and
+.Fn inflate
+can be called again to continue the operation as if
+.Dv Z_NO_FLUSH
+had been used.
+.
+.Pp
+In this implementation,
+.Fn inflate
+always flushes as much output as possible
+to the output buffer,
+and always uses the faster approach
+on the first call.
+So the effects of the
+.Fa flush
+parameter in this implementation
+are on the return value of
+.Fn inflate
+as noted below,
+when
+.Fn inflate
+returns early when
+.Dv Z_BLOCK
+or
+.Dv Z_TREES
+is used,
+and when
+.Fn inflate
+avoids the allocation of memory
+for a sliding window when
+.Dv Z_FINISH
+is used.
+.
+.Pp
+If a preset dictionary is needed after this call
+.Po
+see
+.Xr inflateSetDictionary 3
+.Pc ,
+.Fn inflate
+sets
+.Fa strm->adler
+to the Adler-32 checksum of the dictionary
+chosen by the compressor
+and returns
+.Dv Z_NEED_DICT ;
+otherwise it sets
+.Fa strm->adler
+to the Adler-32 checksum
+of all output produced so far
+.Po
+that is,
+.Fa total_out
+bytes
+.Pc
+and returns
+.Dv Z_OK ,
+.Dv Z_STREAM_END
+or an error code
+as described in
+.Sx RETURN VALUES .
+At the end of the stream,
+.Fn inflate
+checks that its computed Adler-32 checksum
+is equal to that saved by the compressor
+and returns
+.Dv Z_STREAM_END
+only if the checksum is correct.
+.
+.Pp
+.Fn inflate
+can decompress and check
+either zlib-wrapped or gzip-wrapped
+deflate data.
+The header type is detected automatically,
+if requested when initializing with
+.Xr inflateInit2 3 .
+Any information contained in the gzip header
+is not retained unless
+.Xr inflateGetHeader 3
+is used.
+When processing gzip-wrapped deflate data,
+.Fa strm->adler32
+is set to the CRC-32
+of the output produced so far.
+The CRC-32 is checked against the gzip trailer,
+as is the uncompressed length,
+modulo 2^32.
+.
+.Sh RETURN VALUES
+.Fn inflate
+returns
+.Dv Z_OK
+if some progress has been made
+(more input processed or more output produced),
+.Dv Z_STREAM_END
+if the end of the compressed data has been reached
+and all uncompressed output has been produced,
+.Dv Z_NEED_DICT
+if a preset dictionary is needed at this point,
+.Dv Z_DATA_ERROR
+if the input data was corrupted
+.Po
+input stream not conforming to the zlib format
+or incorrect check value,
+in which case
+.Fa strm->msg
+points to a string with a more specific error
+.Pc ,
+.Dv Z_STREAM_ERROR
+if the stream structure was inconsistent
+.Po
+for example
+.Fa next_in
+or
+.Fa next_out
+was
+.Dv Z_NULL ,
+or the state was inadvertently written over
+by the application
+.Pc ,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_BUF_ERROR
+if no progress was possible
+or if there was not enough room
+in the output buffer when
+.Dv Z_FINISH
+is used.
+Note that
+.Dv Z_BUF_ERROR
+is not fatal,
+and
+.Fn inflate
+can be called again with more input
+and more output space
+to continue decompressing.
+If
+.Dv Z_DATA_ERROR
+is returned,
+the application may then call
+.Xr inflateSync 3
+to look for a good compression block
+if a partial recovery of the data
+is to be attempted.
+.
+.Sh SEE ALSO
+.Xr deflate 3 ,
+.Xr inflateBack 3 ,
+.Xr inflateEnd 3 ,
+.Xr inflateInit 3 ,
+.Xr inflateMark 3 ,
+.Xr inflateSync 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateBack.3 b/doc/zlib/inflateBack.3
new file mode 100644
index 00000000..fcda7452
--- /dev/null
+++ b/doc/zlib/inflateBack.3
@@ -0,0 +1,285 @@
+.Dd January 15, 2017
+.Dt INFLATEBACK 3
+.Os
+.
+.Sh NAME
+.Nm inflateBack
+.Nd inflate call-back interface
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.
+.Ft typedef unsigned
+.Fo (*in_func)
+.Fa "void FAR *"
+.Fa "z_const unsigned char FAR * FAR *"
+.Fc
+.
+.Ft typedef int
+.Fo (*out_func)
+.Fa "void FAR *"
+.Fa "unsigned char FAR *"
+.Fa "unsigned"
+.Fc
+.
+.Ft int
+.Fo inflateBack
+.Fa "z_streamp strm"
+.Fa "in_func in"
+.Fa "void FAR *in_desc"
+.Fa "out_func out"
+.Fa "void FAR *out_desc"
+.Fc
+.
+.Sh DESCRIPTION
+.Fn inflateBack
+does a raw inflate
+with a single call
+using a call-back interface
+for input and output.
+This is potentially more efficient than
+.Xr inflate 3
+for file I/O applications,
+in that it avoids copying between the output
+and the sliding window
+by simply making the window itself the output buffer.
+.Xr inflate 3
+can be faster on modern CPUs
+when used with large buffers.
+.Fn inflateBack
+trusts the application to not change
+the output buffer passed by the output function,
+at least until
+.Fn inflateBack
+returns.
+.
+.Pp
+.Xr inflateBackInit 3
+must be called first
+to allocate the internal state
+and to initialize the state
+with the user-provided window buffer.
+.Fn inflateBack
+may then be used multiple times
+to inflate a complete,
+raw deflate stream
+with each call.
+.Xr inflateBackEnd 3
+is then called to free the allocated state.
+.
+.Pp
+A raw deflate stream
+is one with no zlib or gzip header or trailer.
+This routine would normally be used
+in a utility that reads zip or gzip files
+and write out uncompressed files.
+The utility would decode the header
+and process the trailer on its own,
+hence this routine expects only
+the raw deflate stream to decompress.
+This is different from the default behaviour of
+.Xr inflate 3 ,
+which expects a zlib header and trailer
+around the deflate stream.
+.
+.Pp
+.Fn inflateBack
+uses two subroutines
+supplied by the caller
+that are then called by
+.Fn inflateBack
+for input and output.
+.Fn inflateBack
+calls those routines
+until it reads a complete deflate stream
+and writes out all of the uncompressed data,
+or until it encounters an error.
+The function's parameters and return types
+are defined above in the
+.Vt in_func
+and
+.Vt out_func
+typedefs.
+.Fn inflateBack
+will call
+.Fn in in_desc &buf
+which should return
+the number of bytes of provided input,
+and a pointer to that input in
+.Fa buf .
+If there is no input available,
+.Fn in
+must return zero \(em
+.Fa buf
+is ignored in that case \(em
+and
+.Fn inflateBack
+will return a buffer error.
+.Fn inflateBack
+will call
+.Fn out out_desc buf len
+to write the uncompressed data
+.Fa buf[0..len-1] .
+.Fn out
+should return zero on success,
+or non-zero on failure.
+If
+.Fn out
+returns non-zero,
+.Fn inflateBack
+will return with an error.
+Neither
+.Fn in
+nor
+.Fn out
+are permitted to change
+the contents of the window provided to
+.Xr inflateBackInit 3 ,
+which is also the buffer that
+.Fn out
+uses to write from.
+The length written by
+.Fn out
+will be at most the window size.
+Any non-zero amount of input
+may be provided by
+.Fn in .
+.
+.Pp
+For convenience,
+.Fn inflateBack
+can be provided input on the first call
+by setting
+.Fa strm->next_in
+and
+.Fa strm->avail_in .
+If that input is exhausted,
+then
+.Fn in
+will be called.
+Therefore
+.Fa strm->next_in
+must be initialized before calling
+.Fn inflateBack .
+If
+.Fa strm->next_in
+is
+.Dv Z_NULL ,
+then
+.Fn in
+will be called immediately for input.
+If
+.Fa strm->next_in
+is not
+.Dv Z_NULL ,
+then
+.Fa strm->avail_in
+must also be initialized,
+and then if
+.Fa strm->avail_in
+is not zero,
+input will initially be taken from
+.Fa "strm->next_in[0 .. strm->avail_in - 1]" .
+.
+.Pp
+The
+.Fa in_desc
+and
+.Fa out_desc
+parameters of
+.Fn inflateBack
+is passed as the first parameter of
+.Fn in
+and
+.Fn out
+respectively when they are called.
+These descriptors can be optionally used
+to pass any information that the caller-supplied
+.Fn in
+and
+.Fn out
+functions need to do their job.
+.
+.Sh RETURN VALUES
+On return,
+.Fn inflateBack
+will set
+.Fa strm->next_in
+and
+.Fa strm->avail_in
+to pass back any unused input
+that was provided by the last
+.Fn in
+call.
+The return values of
+.Fn inflateBack
+can be
+.Dv Z_STREAM_END
+on success,
+.Dv Z_BUF_ERROR
+if
+.Fn in
+or
+.Fn out
+returned an error,
+.Dv Z_DATA_ERROR
+if there was a format error
+in the deflate stream
+.Po
+in which case
+.Fa strm->msg
+is set to indicate the nature of the error
+.Pc ,
+or
+.Dv Z_STREAM_ERROR
+if the stream was not properly initialized.
+In the case of
+.Dv Z_BUF_ERROR ,
+an input or output error can be distinguished using
+.Fa strm->next_in
+which will be
+.Dv Z_NULL
+only if
+.Fn in
+returned an error.
+If
+.Fa strm->next_in
+is not
+.Dv Z_NULL ,
+then the
+.Dv Z_BUF_ERROR
+was due to
+.Fn out
+returning non-zero.
+.Po
+.Fn in
+will always be called before
+.Fn out ,
+so
+.Fa strm->next_in
+is assured to be defined if
+.Fa out
+returns non-zero.
+.Pc \&
+Note that
+.Fn inflateBack
+cannot return
+.Dv Z_OK .
+.
+.Sh SEE ALSO
+.Xr inflate 3 ,
+.Xr inflateBackEnd 3 ,
+.Xr inflateBackInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateBackEnd.3 b/doc/zlib/inflateBackEnd.3
new file mode 100644
index 00000000..39fbea8f
--- /dev/null
+++ b/doc/zlib/inflateBackEnd.3
@@ -0,0 +1,43 @@
+.Dd January 15, 2017
+.Dt INFLATEBACKEND 3
+.Os
+.
+.Sh NAME
+.Nm inflateBackEnd
+.Nd free inflateBack stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateBackEnd "z_streamp strm"
+.
+.Sh DESCRIPTION
+All memory allocated by
+.Xr inflateBackInit 3
+is freed.
+.
+.Sh RETURN VALUES
+.Fn inflateBackEnd
+returns
+.Dv Z_OK
+on success,
+or
+.Dv Z_STREAM_ERROR
+if the stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr inflateBack 3 ,
+.Xr inflateBackInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateBackInit.3 b/doc/zlib/inflateBackInit.3
new file mode 100644
index 00000000..d029542e
--- /dev/null
+++ b/doc/zlib/inflateBackInit.3
@@ -0,0 +1,84 @@
+.Dd January 15, 2017
+.Dt INFLATEBACKINIT 3
+.Os
+.
+.Sh NAME
+.Nm inflateBackInit
+.Nd initialize inflateBack stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fo inflateBackInit
+.Fa "z_streamp strm"
+.Fa "int windowBits"
+.Fa "unsigned char FAR *window"
+.Fc
+.
+.Sh DESCRIPTION
+Initialize the internal stream state
+for decompression using
+.Xr inflateBack 3
+calls.
+The fields
+.Fa zalloc ,
+.Fa zfree
+and
+.Fa opaque
+in
+.Fa strm
+must be initialized before the call.
+If
+.Fa zalloc
+and
+.Fa zfree
+are
+.Dv Z_NULL ,
+then the default
+library-derived memory allocation routines are used.
+.Fa windowBits
+is the base two logarithm of the window size,
+in the range 8..15.
+.Fa window
+is a caller supplied buffer of that size.
+Except for special applications
+where it is assured that deflate
+was used with small window sizes,
+.Fa windowBits
+must be 15
+and a 32K byte
+.Fa window
+must be supplied
+to be able to decompress general deflate streams.
+.
+.Sh RETURN VALUES
+.Fn inflateBackInit
+will return
+.Dv Z_OK
+on success,
+.Dv Z_STREAM_ERROR
+if any of the parameters are invalid,
+.Dv Z_MEM_ERROR
+if the internal state could not be allocated,
+or
+.Dv Z_VERSION_ERROR
+if the version of the library
+does not match the version of the header file.
+.
+.Sh SEE ALSO
+.Xr inflateBack 3 ,
+.Xr inflateBackEnd 3 ,
+.Xr inflateInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateCopy.3 b/doc/zlib/inflateCopy.3
new file mode 100644
index 00000000..167b879b
--- /dev/null
+++ b/doc/zlib/inflateCopy.3
@@ -0,0 +1,59 @@
+.Dd January 15, 2017
+.Dt INFLATECOPY 3
+.Os
+.
+.Sh NAME
+.Nm inflateCopy
+.Nd copy inflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateCopy "z_streamp dest" "z_streamp source"
+.
+.Sh DESCRIPTION
+Sets the destination stream
+as a complete copy of the source stream.
+.
+.Pp
+This function can be useful
+when randomly accessing a large stream.
+The first pass through the stream
+can periodically record the inflate state,
+allowing restarting inflate at those points
+when randomly accessing the stream.
+.
+.Sh RETURN VALUES
+.Fn inflateCopy
+returns
+.Dv Z_OK
+if success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent
+.Po
+such as
+.Fa zalloc
+being
+.Dv Z_NULL
+.Pc .
+.Fa msg
+is left unchanged
+in both source and destination.
+.
+.Sh SEE ALSO
+.Xr inflateInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateEnd.3 b/doc/zlib/inflateEnd.3
new file mode 100644
index 00000000..54945b50
--- /dev/null
+++ b/doc/zlib/inflateEnd.3
@@ -0,0 +1,44 @@
+.Dd January 15, 2017
+.Dt INFLATEEND 3
+.Os
+.
+.Sh NAME
+.Nm inflateEnd
+.Nd free inflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateEnd "z_streamp strm"
+.
+.Sh DESCRIPTION
+All dynamically allocated data structures
+for this stream are feed.
+This function discards any unprocessed input
+and does not flush any pending output.
+.
+.Sh RETURN VALUES
+.Fn inflateEnd
+returns
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if the stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr inflate 3 ,
+.Xr inflateInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateGetDictionary.3 b/doc/zlib/inflateGetDictionary.3
new file mode 100644
index 00000000..9290850c
--- /dev/null
+++ b/doc/zlib/inflateGetDictionary.3
@@ -0,0 +1,69 @@
+.Dd January 15, 2017
+.Dt INFLATEGETDICTIONARY 3
+.Os
+.
+.Sh NAME
+.Nm inflateGetDictionary
+.Nd inflate sliding dictionary
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fo inflateGetDictionary
+.Fa "z_streamp strm"
+.Fa "Bytef *dictionary"
+.Fa "uInt *dictLength"
+.Fc
+.
+.Sh DESCRIPTION
+Returns the sliding dictionary
+being maintained by
+.Xr inflate 3 .
+.Fa dictLength
+is set to the number of bytes
+in the dictionary,
+and that many bytes are copied to
+.Fa dictionary .
+.Fa dictionary
+must have enough space,
+where 32768 bytes is always enough.
+If
+.Fn inflateGetDictionary
+is called with
+.Fa dictionary
+equal to
+.Dv Z_NULL ,
+then only the dictionary length is returned,
+and nothing is copied.
+Similarly,
+if
+.Fa dictLength
+is
+.Dv Z_NULL ,
+then it is not set.
+.
+.Sh RETURN VALUES
+.Fn inflateGetDictionary
+returns
+.Dv Z_OK
+on success,
+or
+.Dv Z_STREAM_ERROR
+if the stream state is inconsistent.
+.
+.Sh SEE ALSO
+.Xr deflateSetDictionary 3 ,
+.Xr inflateSetDictionary 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateGetHeader.3 b/doc/zlib/inflateGetHeader.3
new file mode 100644
index 00000000..57f7c443
--- /dev/null
+++ b/doc/zlib/inflateGetHeader.3
@@ -0,0 +1,170 @@
+.Dd January 15, 2017
+.Dt INFLATEGETHEADER 3
+.Os
+.
+.Sh NAME
+.Nm inflateGetHeader
+.Nd get gzip header
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateGetHeader "z_streamp strm" "gz_headerp head"
+.
+.Sh DESCRIPTION
+.Fn inflateGetHeader
+requests that gzip header information
+be stored in the provided
+.Vt gz_header
+structure.
+.Fn inflateGetHeader
+may be called after
+.Xr inflateInit2 3
+or
+.Xr inflateReset 3 ,
+and before the first call of
+.Xr inflate 3 .
+As
+.Xr inflate 3
+processes the gzip stream,
+.Fa head->done
+is zero until the header is completed,
+at which time
+.Fa head->done
+is set to one.
+If a zlib stream is being decoded,
+then
+.Fa head->done
+is set to -1 to indicate that
+there will be no gzip header information forthcoming.
+Note that
+.Dv Z_BLOCK
+or
+.Dv Z_TREES
+can be used to force
+.Xr inflate 3
+to return immediately after
+header processing is complete
+and before any actual data is decompressed.
+.
+.Pp
+The
+.Fa text ,
+.Fa time ,
+.Fa xflags ,
+and
+.Fa os
+fields are filled in with the gzip header contents.
+.Fa hcrc
+is set to true if there is a header CRC.
+.Po
+The header CRC was valid if
+.Fa done
+is set to one.
+.Pc \&
+If
+.Fa extra
+is not
+.Dv Z_NULL ,
+then
+.Fa extra_max
+contains the maximum number of bytes to write to
+.Fa extra .
+Once
+.Fa done
+is true,
+.Fa extra_len
+contains the actual extra field length,
+and
+.Fa extra
+contains the extra field,
+or that field truncated if
+.Fa extra_max
+is less than
+.Fa extra_len .
+If
+.Fa name
+is not
+.Dv Z_NULL ,
+then up to
+.Fa name_max
+characters are written there,
+terminated with a zero
+unless the length is greater than
+.Fa name_max .
+If
+.Fa comment
+is not
+.Dv Z_NULL ,
+then up to
+.Fa comm_max
+characters are written there,
+terminated with a zero
+unless the length is greater than
+.Fa comm_max .
+When any of
+.Fa extra ,
+.Fa name ,
+or
+.Fa comment
+are not
+.Dv Z_NULL
+and the respective field
+is not present in the header,
+then that field is set to
+.Dv Z_NULL
+to signal its absence.
+This allows the use of
+.Xr deflateSetHeader 3
+with the returned structure
+to duplicate the header.
+However if those fields are set to allocated memory,
+then the application will need to
+save those pointers elsewhere
+so that they can be eventually feed.
+.
+.Pp
+If
+.Fn inflateGetHeader
+is not used,
+then the header information is simply discarded.
+The header is always checked for validity,
+including the header CRC if present.
+.Xr inflateReset 3
+will reset the process to discard the header information.
+The application would need to call
+.Fn inflateGetHeader
+again to retrieve the header from the next gzip stream.
+.
+.Pp
+The
+.Vt gz_headerp
+type is documented in
+.Xr deflateSetHeader 3 .
+.
+.Sh RETURN VALUES
+.Fn inflateGetHeader
+returns
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr gzip 1 ,
+.Xr deflateSetHeader 3 ,
+.Xr inflateInit2 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateInit.3 b/doc/zlib/inflateInit.3
new file mode 100644
index 00000000..66a1d4f7
--- /dev/null
+++ b/doc/zlib/inflateInit.3
@@ -0,0 +1,101 @@
+.Dd January 15, 2017
+.Dt INFLATEINIT 3
+.Os
+.
+.Sh NAME
+.Nm inflateInit
+.Nd initialize inflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateInit "z_streamp strm"
+.
+.Sh DESCRIPTION
+Initializes the internal stream state for decompression.
+The fields
+.Fa next_in ,
+.Fa avail_in ,
+.Fa zalloc ,
+.Fa zfree
+and
+.Fa opaque
+must be initialized before by the caller.
+In the current version of
+.Fn inflateInit ,
+the provided input is not read or consumed.
+The allocation of a sliding window
+will be deferred to the first call of
+.Xr inflate 3
+(if the decompression does not complete on the first call).
+If
+.Fa zalloc
+and
+.Fa zfree
+are set to
+.Dv Z_NULL ,
+.Fn inflateInit
+updates them to use default allocation functions.
+.
+.Pp
+.Fn inflateInit
+does not perform any decompression.
+Actual decompression will be done by
+.Xr inflate 3 .
+So
+.Fa next_in ,
+.Fa avail_in ,
+.Fa next_out
+and
+.Fa avail_out
+are unused and unchanged.
+The current implementation of
+.Fn inflateInit
+does not process any header information \(em
+that is deferred until
+.Xr inflate 3
+is called.
+.
+.Pp
+The
+.Vt z_streamp
+type is documented in
+.Xr deflateInit 3 .
+.
+.Sh RETURN VALUES
+.Fn inflateInit
+returns
+.Dv Z_OK
+if success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_VERSION_ERROR
+if the zlib library version
+is incompatible with the version assumed by the caller,
+or
+.Dv Z_STREAM_ERROR
+if the parameters are invalid,
+such as a null pointer to the structure.
+.Fa msg
+is set to null if there is no error message.
+.
+.Sh SEE ALSO
+.Xr inflate 3 ,
+.Xr inflateBackInit 3 ,
+.Xr inflateCopy 3 ,
+.Xr inflateEnd 3 ,
+.Xr inflateInit2 3 ,
+.Xr inflateSetDictionary 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateInit2.3 b/doc/zlib/inflateInit2.3
new file mode 100644
index 00000000..5b8b49ac
--- /dev/null
+++ b/doc/zlib/inflateInit2.3
@@ -0,0 +1,181 @@
+.Dd January 15, 2017
+.Dt INFLATEINIT2 3
+.Os
+.
+.Sh NAME
+.Nm inflateInit2
+.Nd inflate compression options
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateInit2 "z_streamp strm" "int windowBits"
+.
+.Sh DESCRIPTION
+This is another version of
+.Xr inflateInit 3
+with an extra parameter.
+The fields
+.Fa next_in ,
+.Fa avail_in ,
+.Fa zalloc ,
+.Fa zfree
+and
+.Fa opaque
+must be initialized before by the caller.
+.
+.Pp
+The
+.Fa windowBits
+parameter is the base two logarithm
+of the maximum window size
+(the size of the history buffer).
+It should be in the range 8..15
+for this version of the library.
+The default value is 15 if
+.Xr inflateInit 3
+is used instead.
+.Fa windowBits
+must be greater than or equal to the
+.Fa windowBits
+value provided to
+.Xr deflateInit2 3
+while compressing,
+or it must be equal to 15 if
+.Xr deflateInit2 3
+was not used.
+If a compressed stream with a larger window size
+is given as input,
+.Xr inflate 3
+will return with the error code
+.Dv Z_DATA_ERROR
+instead of trying to allocate a larger window.
+.
+.Pp
+.Fa windowBits
+can also be zero
+to request that
+.Xr inflate 3
+use the window size
+in the zlib header
+of the compressed stream.
+.
+.Pp
+.Fa windowBits
+can also be -8..-15
+for raw inflate.
+In this case,
+.Fa -windowBits
+determines the window size.
+.Xr inflate 3
+will then process raw deflate data,
+not looking for a zlib or gzip header,
+not generating a check value,
+and not looking for any check values
+for comparison at the end of the stream.
+This is for use with other formats
+that use the deflate compressed data format
+such as zip.
+Those formats provide their own check values.
+If a custom format is developed
+using the raw deflate format for compressed data,
+it is recommended that a check value
+such as an Adler-32 or a CRC-32
+be applied to the uncompressed data
+as is done in the zlib, gzip and zip formats.
+For most applications,
+the zlib format should be used as is.
+Note that comments above on the use in
+.Xr deflateInit2 3
+applies to the magnitude of
+.Fa windowBits .
+.
+.Pp
+.Fa windowBits
+can also be greater than 15
+for optional gzip decoding.
+Add 32 to
+.Fa windowBits
+to enable zlib and gzip decoding
+with automatic header detection,
+or add 16 to decode only the gzip format
+.Po
+the zlib format will return a
+.Dv Z_DATA_ERROR
+.Pc .
+If a gzip stream is being decoded,
+.Fa strm->adler
+is a CRC-32 instead of an Adler-32.
+Unlike the
+.Xr gunzip 1
+utility and
+.Xr gzread 3 ,
+.Xr inflate 3
+will not automatically decode
+concatenated gzip streams.
+.Xr inflate 3
+will return
+.Dv Z_STREAM_END
+at the end of the gzip stream.
+The state would need to be reset
+to continue decoding a subsequent gzip stream.
+.
+.Pp
+.Fn inflateInit2
+does not perform any decompression
+apart from possibly reading the zlib header if present:
+actual decompression will be done by
+.Xr inflate 3 .
+.Po
+So
+.Fa next_in
+and
+.Fa avail_in
+may be modified,
+but
+.Fa next_out
+and
+.Fa avail_out
+are unused and unchanged.
+.Pc \&
+The current implementation of
+.Fn inflateInit2
+does not process any header information \(em
+that is deferred until
+.Xr inflate 3
+is called.
+.
+.Sh RETURN VALUES
+.Fn inflateInit2
+returns
+.Dv Z_OK
+if success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_VERSION_ERROR
+if the zlib library version
+is incompatible with the version assumed by the caller,
+or
+.Dv Z_STREAM_ERROR
+if the parameters are invalid,
+such as a null pointer to the structure.
+.Fa msg
+is set to null if there is no error message.
+.
+.Sh SEE ALSO
+.Xr deflateInit2 3 ,
+.Xr inflateInit 3 ,
+.Xr inflatePrime 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateMark.3 b/doc/zlib/inflateMark.3
new file mode 100644
index 00000000..90e2ee0b
--- /dev/null
+++ b/doc/zlib/inflateMark.3
@@ -0,0 +1,88 @@
+.Dd January 15, 2017
+.Dt INFLATEMARK 3
+.Os
+.
+.Sh NAME
+.Nm inflateMark
+.Nd mark location for random access
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft long
+.Fn inflateMark "z_streamp strm"
+.
+.Sh DESCRIPTION
+This function returns two values,
+one in the lower 16 bits of the return value,
+and the other in the remaining upper bits,
+obtained by shifting the return value down 16 bits.
+If the upper value is -1
+and the lower value is zero,
+then
+.Xr inflate 3
+is currently decoding information outside of a block.
+If the upper value is -1
+and the lower value is non-zero,
+then
+.Xr inflate 3
+is in the middle of a stored block,
+with the lower value equaling
+the number of bytes from the input remaining to copy.
+If the upper value is not -1,
+then it is the number of bits
+back from the current bit position
+in the input of the code
+(literal of length/distance pair)
+currently being processed.
+In that case the lower value
+is the number of bytes
+already emitted for that code.
+.
+.Pp
+A code is being processed if
+.Xr inflate 3
+is waiting for more input to complete
+decoding of the code,
+or if it has completed decoding
+but is waiting for more output space
+to write the literal or match data.
+.
+.Pp
+.Fn inflateMark
+is used to mark locations in the input data
+for random access,
+which may be at bit positions,
+and to note those cases where
+the output of a code may span boundaries
+of random access blocks.
+The current location in the input stream
+can be determined from
+.Fa avail_in
+and
+.Fa data_type
+as noted in the description for the
+.Dv Z_BLOCK
+.Fa flush
+parameter for
+.Xr inflate 3 .
+.
+.Sh RETURN VALUES
+.Fn inflateMark
+returns the value noted above,
+or -65536 if the provided source stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr inflate 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflatePrime.3 b/doc/zlib/inflatePrime.3
new file mode 100644
index 00000000..66953665
--- /dev/null
+++ b/doc/zlib/inflatePrime.3
@@ -0,0 +1,73 @@
+.Dd January 15, 2017
+.Dt INFLATEPRIME 3
+.Os
+.
+.Sh NAME
+.Nm inflatePrime
+.Nd insert bits in inflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflatePrime "z_streamp strm" "int bits" "int value"
+.
+.Sh DESCRIPTION
+This function inserts bits
+in the inflate input stream.
+The intent is that this function
+is used to start inflating
+at a bit position
+in the middle of a byte.
+The provided bits will be used
+before any bytes are used from
+.Fa next_in .
+This function should only be used with raw inflate,
+and should be used before the first
+.Xr inflate 3
+call after
+.Xr inflateInit2 3
+or
+.Xr inflateReset 3 .
+.Fa bits
+must be less than or equal to 16,
+and that many of the least significant bits of
+.Fa value
+will be inserted in the input.
+.
+.Pp
+If
+.Fa bits
+is negative,
+then the input stream bit buffer is emptied.
+Then
+.Fn inflatePrime
+can be called again
+to put bits in the buffer.
+This is used to clear out bits leftover
+after feeding inflate a block description
+prior to feeding inflate codes.
+.
+.Sh RETURN VALUES
+.Fn inflatePrime
+returns
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent.
+.
+.Sh SEE ALSO
+.Xr inflateInit2 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateReset.3 b/doc/zlib/inflateReset.3
new file mode 100644
index 00000000..53c4ffe2
--- /dev/null
+++ b/doc/zlib/inflateReset.3
@@ -0,0 +1,81 @@
+.Dd January 15, 2017
+.Dt INFLATERESET 3
+.Os
+.
+.Sh NAME
+.Nm inflateReset ,
+.Nm inflateReset2
+.Nd reset inflate stream
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateReset "z_streamp strm"
+.Ft int
+.Fn inflateReset2 "z_streamp strm" "int windowBits"
+.
+.Sh DESCRIPTION
+This function is equivalent to
+.Xr inflateEnd 3
+followed by
+.Xr inflateInit 3 ,
+but does not free and reallocate
+the internal decompression state.
+The stream will keep attributes
+that may have been set by
+.Xr inflateInit2 3 .
+.
+.Pp
+.Fn inflateReset2
+is the same as
+.Fn inflateReset ,
+but it also permits changing
+the wrap and window size requests.
+The
+.Fa windowBits
+parameter is interpreted the same as it is for
+.Xr inflateInit2 3 .
+If the window size is changed,
+then the memory allocated for the window is freed,
+and the window will be reallocated by
+.Xr inflate 3
+if needed.
+.
+.Sh RETURN VALUES
+.Fn inflateReset
+and
+.Fn inflateReset2
+return
+.Dv Z_OK
+if success,
+or
+.Dv Z_STREAM_ERROR
+if the source stream state was inconsistent
+.Po
+such as
+.Fa zalloc
+or
+.Fa state
+being
+.Dv Z_NULL
+.Pc ,
+or if the
+.Fa windowBits
+parameter is invalid.
+.
+.Sh SEE ALSO
+.Xr inflateEnd 3 ,
+.Xr inflateInit 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateSetDictionary.3 b/doc/zlib/inflateSetDictionary.3
new file mode 100644
index 00000000..291c97e8
--- /dev/null
+++ b/doc/zlib/inflateSetDictionary.3
@@ -0,0 +1,85 @@
+.Dd January 15, 2017
+.Dt INFLATESETDICTIONARY 3
+.Os
+.
+.Sh NAME
+.Nm inflateSetDictionary
+.Nd initialize decompression dictionary
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fo inflateSetDictionary
+.Fa "z_streamp strm"
+.Fa "const Bytef *dictionary"
+.Fa "uInt dictLength"
+.Fc
+.
+.Sh DESCRIPTION
+Initializes the decompression dictionary
+from the given uncompressed byte sequence.
+This function must be called
+immediately after a call of
+.Xr inflate 3 ,
+if that call returned
+.Dv Z_NEED_DICT .
+The dictionary chosen by the compressor
+can be determined from the Adler-32 value
+returned by that call of
+.Xr inflate 3 .
+The compressor and decompressor
+must use exactly the same dictionary
+.Po
+see
+.Xr deflateSetDictionary 3
+.Pc .
+For raw inflate,
+this function can be called at any time
+to set the dictionary.
+If the provided dictionary
+is smaller than the window
+and there is already data in the window,
+then the provided dictionary
+will amend what's there.
+The application must insure that the dictionary
+that was used for compression is provided.
+.
+.Pp
+.Fn inflateSetDictionary
+does not perform any decompression:
+this will be done by subsequent calls of
+.Xr inflate 3 .
+.
+.Sh RETURN VALUES
+.Fn inflateSetDictionary
+returns
+.Dv Z_OK
+if success,
+.Dv Z_STREAM_ERROR
+if a parameter is invalid
+.Po
+e.g. dictionary being
+.Dv Z_NULL
+.Pc
+or the stream state is inconsistent,
+.Dv Z_DATA_ERROR
+if the given dictionary
+doesn't match the expected one
+(incorrect Adler-32 value).
+.
+.Sh SEE ALSO
+.Xr deflateGetDictionary 3 ,
+.Xr inflateGetDictionary 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/inflateSync.3 b/doc/zlib/inflateSync.3
new file mode 100644
index 00000000..56d3ca28
--- /dev/null
+++ b/doc/zlib/inflateSync.3
@@ -0,0 +1,72 @@
+.Dd January 15, 2017
+.Dt INFLATESYNC 3
+.Os
+.
+.Sh NAME
+.Nm inflateSync
+.Nd skip invalid data
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft int
+.Fn inflateSync "z_streamp strm"
+.
+.Sh DESCRIPTION
+Skips invalid compressed data
+until a possible full flush point
+.Po
+see
+.Xr deflate 3
+for the description of
+.Dv Z_FULL_FLUSH
+.Pc
+can be found,
+or until all available input is skipped.
+No output is provided.
+.
+.Pp
+.Fn inflateSync
+searches for a 00 00 FF FF pattern
+in the compressed data.
+All full flush points have this pattern,
+but not all occurrences of this pattern
+are full flush points.
+.
+.Sh RETURN VALUES
+.Fn inflateSync
+returns
+.Dv Z_OK
+if a possible full flush point has been found,
+.Dv Z_BUF_ERROR
+if no more input was provided,
+.Dv Z_DATA_ERROR
+if no flush point has been found,
+or
+.Dv Z_STREAM_ERROR
+if the stream structure was inconsistent.
+In the success case,
+the application may save the current value of
+.Fa total_in
+which indicates where valid compressed data was found.
+In the error case,
+the application may repeatedly call
+.Fn inflateSync ,
+providing more input each time,
+until success or the end of the input data.
+.
+.Sh SEE ALSO
+.Xr deflate 3 ,
+.Xr inflate 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/uncompress.3 b/doc/zlib/uncompress.3
new file mode 100644
index 00000000..1047ad91
--- /dev/null
+++ b/doc/zlib/uncompress.3
@@ -0,0 +1,92 @@
+.Dd January 15, 2017
+.Dt UNCOMPRESS 3
+.Os
+.
+.Sh NAME
+.Nm uncompress ,
+.Nm uncompress2
+.Nd decompress source buffer into destination buffer
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.
+.Ft int
+.Fo uncompress
+.Fa "Bytef *dest"
+.Fa "uLongf *destLen"
+.Fa "const Bytef *source"
+.Fa "uLong sourceLen"
+.Fc
+.
+.Ft int
+.Fo uncompress2
+.Fa "Bytef *dest"
+.Fa "uLongf *destLen"
+.Fa "const Bytef *source"
+.Fa "uLong *sourceLen"
+.Fc
+.
+.Sh DESCRIPTION
+Decompresses the source buffer into the destination buffer.
+.Fa sourceLen
+is the byte length of the source buffer.
+Upon entry,
+.Fa destLen
+is the total size of the destination buffer,
+which must be large enough to hold the entire uncompressed data.
+.Po
+The size of the uncompressed data
+must have been saved previously by the compressor
+and transmitted to the decompressor
+by some mechanism outside the scope of this compression library.
+.Pc \&
+Upon exit,
+.Fa destLen
+is the actual size of the uncompressed data.
+.
+.Pp
+.Fn uncompress2
+is the same as
+.Fn uncompress ,
+except that
+.Fa sourceLen
+is a pointer,
+where the length of the source is
+.Fa *sourceLen .
+On return,
+.Fa *sourceLen
+is the number of source bytes consumed.
+.
+.Sh RETURN VALUES
+.Fn uncompress
+returns
+.Dv Z_OK
+if success,
+.Dv Z_MEM_ERROR
+if there was not enough memory,
+.Dv Z_BUF_ERROR
+if there was not enough room in the output buffer,
+or
+.Dv Z_DATA_ERROR
+if the input data was corrupted or incomplete.
+In the case where there is not enough room,
+.Fn uncompress
+will fill the output buffer
+with the uncompressed data up to that point.
+.
+.Sh SEE ALSO
+.Xr compress 3 ,
+.Xr inflate 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/zlibCompileFlags.3 b/doc/zlib/zlibCompileFlags.3
new file mode 100644
index 00000000..59cc24a8
--- /dev/null
+++ b/doc/zlib/zlibCompileFlags.3
@@ -0,0 +1,163 @@
+.Dd January 15, 2017
+.Dt ZLIBCOMPILEFLAGS 3
+.Os
+.
+.Sh NAME
+.Nm zlibCompileFlags
+.Nd zlib compile-time options
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Ft uLong
+.Fn zlibCompileFlags void
+.
+.Sh DESCRIPTION
+Return flags indicating compile-time options.
+.
+.Ss Type sizes
+Two bits each,
+00 = 16 bits,
+01 = 32 bits,
+10 = 64 bits,
+11 = other.
+.
+.Pp
+.Bl -tag -width Ds -compact
+.It 1.0
+size of
+.Vt uInt
+.It 3.2
+size of
+.Vt uLong
+.It 5.4
+size of
+.Vt voidpf
+(pointer)
+.It 7.6
+size of
+.Vt z_off_t
+.El
+.
+.Ss Compiler, assembler, and debug options
+.Bl -tag -width Ds -compact
+.It 8
+.Dv ZLIB_DEBUG
+.It 9
+.Dv ASMV
+or
+.Dv ASMINF
+\(em
+use ASM code
+.It 10
+.Dv ZLIB_WINAPI
+\(em
+exported functions use the WINAPI calling convention
+.It 11
+0 (reserved)
+.El
+.
+.Ss One-time table building
+Smaller code,
+but not thread-safe if true.
+.
+.Pp
+.Bl -tag -width Ds -compact
+.It 12
+.Dv BUILDFIXED
+\(em
+build static block decoding tables when needed
+.It 13
+.Dv DYNAMIC_CRC_TABLE
+\(em
+build CRC calculation tables when needed
+.It 14,15
+0 (reserved)
+.El
+.
+.Ss Library content
+Indicates missing functionality.
+.
+.Pp
+.Bl -tag -width Ds -compact
+.It 16
+.Dv NO_GZCOMPRESS
+\(em
+gz* functions cannot compress
+(to avoid linking deflate code when not needed)
+.It 17
+.Dv NO_GZIP
+\(em
+.Xr deflate 3
+can't write gzip streams,
+and
+.Xr inflate 3
+can't detect and decode gzip streams
+(to avoid linking crc code)
+.It 18-19
+0 (reserved)
+.El
+.
+.Ss Operation variations
+Changes in library functionality.
+.
+.Pp
+.Bl -tag -width Ds -compact
+.It 20
+.Dv PKZIP_BUG_WORKAROUND
+\(em
+slightly more permissive
+.Xr inflate 3
+.It 21
+.Dv FASTEST
+\(em
+deflate algorithm with only one,
+lowest compression level
+.It 22,23
+0 (reserved)
+.El
+.
+.Ss sprintf variant used by gzprintf
+Zero is best.
+.
+.Pp
+.Bl -tag -width Ds -compact
+.It 24
+0 = vs*,
+1 = s*
+\(em
+1 means limited to 20 arguments after the format
+.It 25
+0 = *nprintf,
+1 = *printf
+\(em
+1 means
+.Xr gzprintf 3
+not secure!
+.It 26
+0 = returns value,
+1 = void
+\(em
+1 means inferred string length returned
+.El
+.
+.Ss Remainder
+.Bl -tag -width Ds -compact
+.It 27-31
+0 (reserved)
+.El
+.
+.Sh SEE ALSO
+.Xr zlibVersion 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/doc/zlib/zlibVersion.3 b/doc/zlib/zlibVersion.3
new file mode 100644
index 00000000..04377527
--- /dev/null
+++ b/doc/zlib/zlibVersion.3
@@ -0,0 +1,45 @@
+.Dd January 15, 2017
+.Dt ZLIBVERSION 3
+.Os
+.
+.Sh NAME
+.Nm zlibVersion
+.Nd check zlib version
+.
+.Sh LIBRARY
+.Lb libz
+.
+.Sh SYNOPSIS
+.In zlib.h
+.Fd #define ZLIB_VERSION \(dq1.2.11\(dq
+.Ft "const char *"
+.Fn zlibVersion void
+.
+.Sh DESCRIPTION
+The application can compare
+.Fn zlibVersion
+and
+.Dv ZLIB_VERSION
+for consistency.
+If the first character differs,
+the library code actually used
+is not compatible with the
+.In zlib.h
+header file used by the application.
+This check is automatically made by
+.Xr deflateInit 3
+and
+.Xr inflateInit 3 .
+.
+.Sh SEE ALSO
+.Xr zlibCompileFlags 3
+.
+.Sh HISTORY
+This manual page was converted from
+.In zlib.h
+to mdoc format by
+.An June McEnroe Aq Mt june@causal.agency .
+.
+.Sh AUTHORS
+.An Jean-loup Gailly Aq Mt jloup@gzip.org
+.An Mark Adler Aq Mt madler@alumni.caltech.edu
diff --git a/etc/CodeQWERTY.bundle/Contents/Info.plist b/etc/CodeQWERTY.bundle/Contents/Info.plist
new file mode 100644
index 00000000..f78351e8
--- /dev/null
+++ b/etc/CodeQWERTY.bundle/Contents/Info.plist
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+	<dict>
+		<key>CFBundleIdentifier</key>
+		<string>agency.causal.keyboardlayout.code</string>
+		<key>CFBundleName</key>
+		<string>Code QWERTY</string>
+		<key>CFBundleVersion</key>
+		<string>1.0</string>
+		<key>KLInfo_Code QWERTY</key>
+		<dict>
+			<key>TISInputSourceID</key>
+			<string>agency.causal.keyboardlayout.code.qwerty</string>
+			<key>TISIntendedLanguage</key>
+			<string>en-CA</string>
+		</dict>
+	</dict>
+</plist>
diff --git a/etc/CodeQWERTY.bundle/Contents/Resources/CodeQWERTY.keylayout b/etc/CodeQWERTY.bundle/Contents/Resources/CodeQWERTY.keylayout
new file mode 100644
index 00000000..393a86dd
--- /dev/null
+++ b/etc/CodeQWERTY.bundle/Contents/Resources/CodeQWERTY.keylayout
@@ -0,0 +1,1178 @@
+<?xml version="1.1" encoding="UTF-8"?>
+<!DOCTYPE keyboard PUBLIC "" "file://localhost/System/Library/DTDs/KeyboardLayout.dtd">
+<keyboard group="0" id="5069" maxout="1" name="Code QWERTY">
+    <layouts>
+        <layout first="0" last="17" mapSet="16c" modifiers="f4"/>
+        <layout first="18" last="18" mapSet="994" modifiers="f4"/>
+        <layout first="21" last="23" mapSet="994" modifiers="f4"/>
+        <layout first="30" last="30" mapSet="994" modifiers="f4"/>
+        <layout first="194" last="194" mapSet="994" modifiers="f4"/>
+        <layout first="197" last="197" mapSet="994" modifiers="f4"/>
+        <layout first="200" last="201" mapSet="994" modifiers="f4"/>
+        <layout first="206" last="207" mapSet="994" modifiers="f4"/>
+    </layouts>
+    <modifierMap defaultIndex="7" id="f4">
+        <keyMapSelect mapIndex="8">
+            <modifier keys="command?"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="0">
+            <modifier keys="anyShift? caps? command"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="9">
+            <modifier keys="anyShift caps?"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="2">
+            <modifier keys="caps"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="3">
+            <modifier keys="anyOption"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="4">
+            <modifier keys="anyShift caps? anyOption command?"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="5">
+            <modifier keys="caps anyOption"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="6">
+            <modifier keys="caps? anyOption command"/>
+        </keyMapSelect>
+        <keyMapSelect mapIndex="7">
+            <modifier keys="anyShift caps? option? command? control"/>
+            <modifier keys="shift? caps? anyOption command? control"/>
+            <modifier keys="caps? anyOption? command? control"/>
+        </keyMapSelect>
+    </modifierMap>
+    <keyMapSet id="16c">
+        <keyMap index="0">
+            <key action="13" code="0"/>
+            <key code="1" output="s"/>
+            <key code="2" output="d"/>
+            <key code="3" output="f"/>
+            <key code="4" output="h"/>
+            <key code="5" output="g"/>
+            <key code="6" output="z"/>
+            <key code="7" output="x"/>
+            <key code="8" output="c"/>
+            <key code="9" output="v"/>
+            <key code="10" output="§"/>
+            <key code="11" output="b"/>
+            <key code="12" output="q"/>
+            <key code="13" output="w"/>
+            <key action="14" code="14"/>
+            <key code="15" output="r"/>
+            <key action="19" code="16"/>
+            <key code="17" output="t"/>
+            <key code="18" output="1"/>
+            <key code="19" output="2"/>
+            <key code="20" output="3"/>
+            <key code="21" output="4"/>
+            <key code="22" output="6"/>
+            <key code="23" output="5"/>
+            <key code="24" output="="/>
+            <key code="25" output="9"/>
+            <key code="26" output="7"/>
+            <key code="27" output="-"/>
+            <key code="28" output="8"/>
+            <key code="29" output="0"/>
+            <key code="30" output="]"/>
+            <key action="17" code="31"/>
+            <key action="18" code="32"/>
+            <key code="33" output="["/>
+            <key action="15" code="34"/>
+            <key code="35" output="p"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="l"/>
+            <key code="38" output="j"/>
+            <key code="39" output="&#x0027;"/>
+            <key code="40" output="k"/>
+            <key code="41" output=";"/>
+            <key code="42" output="\"/>
+            <key code="43" output=","/>
+            <key code="44" output="/"/>
+            <key action="16" code="45"/>
+            <key code="46" output="m"/>
+            <key code="47" output="."/>
+            <key code="48" output="&#x0009;"/>
+            <key action="5" code="49"/>
+            <key code="50" output="`"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="&#x001D;"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="&#x001C;"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="&#x001F;"/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="&#x001E;"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="1">
+            <key action="6" code="0"/>
+            <key code="1" output="S"/>
+            <key code="2" output="D"/>
+            <key code="3" output="F"/>
+            <key code="4" output="H"/>
+            <key code="5" output="G"/>
+            <key code="6" output="Z"/>
+            <key code="7" output="X"/>
+            <key code="8" output="C"/>
+            <key code="9" output="V"/>
+            <key code="10" output="±"/>
+            <key code="11" output="B"/>
+            <key code="12" output="Q"/>
+            <key code="13" output="W"/>
+            <key action="7" code="14"/>
+            <key code="15" output="R"/>
+            <key action="12" code="16"/>
+            <key code="17" output="T"/>
+            <key code="18" output="!"/>
+            <key code="19" output="@"/>
+            <key code="20" output="#"/>
+            <key code="21" output="$"/>
+            <key code="22" output="^"/>
+            <key code="23" output="%"/>
+            <key code="24" output="+"/>
+            <key code="25" output="("/>
+            <key code="26" output="&#x0026;"/>
+            <key code="27" output="_"/>
+            <key code="28" output="*"/>
+            <key code="29" output=")"/>
+            <key code="30" output="}"/>
+            <key action="10" code="31"/>
+            <key action="11" code="32"/>
+            <key code="33" output="{"/>
+            <key action="8" code="34"/>
+            <key code="35" output="P"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="L"/>
+            <key code="38" output="J"/>
+            <key code="39" output="&#x0022;"/>
+            <key code="40" output="K"/>
+            <key code="41" output=":"/>
+            <key code="42" output="|"/>
+            <key code="43" output="&#x003C;"/>
+            <key code="44" output="?"/>
+            <key action="9" code="45"/>
+            <key code="46" output="M"/>
+            <key code="47" output="&#x003E;"/>
+            <key code="48" output="&#x0009;"/>
+            <key action="5" code="49"/>
+            <key code="50" output="~"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="*"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="+"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="="/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="/"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="2">
+            <key action="6" code="0"/>
+            <key code="1" output="S"/>
+            <key code="2" output="D"/>
+            <key code="3" output="F"/>
+            <key code="4" output="H"/>
+            <key code="5" output="G"/>
+            <key code="6" output="Z"/>
+            <key code="7" output="X"/>
+            <key code="8" output="C"/>
+            <key code="9" output="V"/>
+            <key code="10" output="§"/>
+            <key code="11" output="B"/>
+            <key code="12" output="Q"/>
+            <key code="13" output="W"/>
+            <key action="7" code="14"/>
+            <key code="15" output="R"/>
+            <key action="12" code="16"/>
+            <key code="17" output="T"/>
+            <key code="18" output="1"/>
+            <key code="19" output="2"/>
+            <key code="20" output="3"/>
+            <key code="21" output="4"/>
+            <key code="22" output="6"/>
+            <key code="23" output="5"/>
+            <key code="24" output="="/>
+            <key code="25" output="9"/>
+            <key code="26" output="7"/>
+            <key code="27" output="-"/>
+            <key code="28" output="8"/>
+            <key code="29" output="0"/>
+            <key code="30" output="]"/>
+            <key action="10" code="31"/>
+            <key action="11" code="32"/>
+            <key code="33" output="["/>
+            <key action="8" code="34"/>
+            <key code="35" output="P"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="L"/>
+            <key code="38" output="J"/>
+            <key code="39" output="&#x0027;"/>
+            <key code="40" output="K"/>
+            <key code="41" output=";"/>
+            <key code="42" output="\"/>
+            <key code="43" output=","/>
+            <key code="44" output="/"/>
+            <key action="9" code="45"/>
+            <key code="46" output="M"/>
+            <key code="47" output="."/>
+            <key code="48" output="&#x0009;"/>
+            <key action="5" code="49"/>
+            <key code="50" output="`"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="&#x001D;"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="&#x001C;"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="&#x001F;"/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="&#x001E;"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="3">
+            <key code="0" output="Ã¥"/>
+            <key code="1" output="ß"/>
+            <key code="2" output="∂"/>
+            <key code="3" output="Æ’"/>
+            <key code="4" output="Ë™"/>
+            <key code="5" output="©"/>
+            <key code="6" output="Ω"/>
+            <key code="7" output="≈"/>
+            <key code="8" output="ç"/>
+            <key code="9" output="√"/>
+            <key code="10" output="§"/>
+            <key code="11" output="∫"/>
+            <key code="12" output="Å“"/>
+            <key code="13" output="∑"/>
+            <key action="0" code="14"/>
+            <key code="15" output="®"/>
+            <key code="16" output="Â¥"/>
+            <key code="17" output="†"/>
+            <key code="18" output="¡"/>
+            <key code="19" output="â„¢"/>
+            <key code="20" output="£"/>
+            <key code="21" output="¢"/>
+            <key code="22" output="§"/>
+            <key code="23" output="∞"/>
+            <key code="24" output="≠"/>
+            <key code="25" output="ª"/>
+            <key code="26" output="¶"/>
+            <key code="27" output="–"/>
+            <key code="28" output="•"/>
+            <key code="29" output="º"/>
+            <key code="30" output="‘"/>
+            <key code="31" output="ø"/>
+            <key action="3" code="32"/>
+            <key code="33" output="“"/>
+            <key action="2" code="34"/>
+            <key code="35" output="Ï€"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="¬"/>
+            <key code="38" output="∆"/>
+            <key code="39" output="æ"/>
+            <key code="40" output="Ëš"/>
+            <key code="41" output="…"/>
+            <key code="42" output="«"/>
+            <key code="43" output="≤"/>
+            <key code="44" output="÷"/>
+            <key action="4" code="45"/>
+            <key code="46" output="µ"/>
+            <key code="47" output="≥"/>
+            <key code="48" output="&#x0009;"/>
+            <key code="49" output=" "/>
+            <key action="1" code="50"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="&#x001D;"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="&#x001C;"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="&#x001F;"/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="&#x001E;"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="4">
+            <key code="0" output="Ã…"/>
+            <key code="1" output="Ã"/>
+            <key code="2" output="ÃŽ"/>
+            <key code="3" output="Ã"/>
+            <key code="4" output="Ó"/>
+            <key code="5" output="Ë"/>
+            <key code="6" output="¸"/>
+            <key code="7" output="Ë›"/>
+            <key code="8" output="Ç"/>
+            <key code="9" output="â—Š"/>
+            <key code="10" output="±"/>
+            <key code="11" output="ı"/>
+            <key code="12" output="Å’"/>
+            <key code="13" output="„"/>
+            <key code="14" output="´"/>
+            <key code="15" output="‰"/>
+            <key code="16" output="Ã"/>
+            <key code="17" output="ˇ"/>
+            <key code="18" output="â„"/>
+            <key code="19" output="€"/>
+            <key code="20" output="‹"/>
+            <key code="21" output="›"/>
+            <key code="22" output="fl"/>
+            <key code="23" output="ï¬"/>
+            <key code="24" output="±"/>
+            <key code="25" output="·"/>
+            <key code="26" output="‡"/>
+            <key code="27" output="—"/>
+            <key code="28" output="°"/>
+            <key code="29" output="‚"/>
+            <key code="30" output="’"/>
+            <key code="31" output="Ø"/>
+            <key code="32" output="¨"/>
+            <key code="33" output="â€"/>
+            <key code="34" output="ˆ"/>
+            <key code="35" output="âˆ"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="Ã’"/>
+            <key code="38" output="Ô"/>
+            <key code="39" output="Æ"/>
+            <key code="40" output=""/>
+            <key code="41" output="Ú"/>
+            <key code="42" output="»"/>
+            <key code="43" output="¯"/>
+            <key code="44" output="¿"/>
+            <key code="45" output="˜"/>
+            <key code="46" output="Â"/>
+            <key code="47" output="˘"/>
+            <key code="48" output="&#x0009;"/>
+            <key code="49" output=" "/>
+            <key code="50" output="`"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="*"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="+"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="="/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="/"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="5">
+            <key code="0" output="Ã…"/>
+            <key code="1" output="Ã"/>
+            <key code="2" output="ÃŽ"/>
+            <key code="3" output="Ã"/>
+            <key code="4" output="Ó"/>
+            <key code="5" output="©"/>
+            <key code="6" output="Ω"/>
+            <key code="7" output="≈"/>
+            <key code="8" output="Ç"/>
+            <key code="9" output="√"/>
+            <key code="10" output="§"/>
+            <key code="11" output="ı"/>
+            <key code="12" output="Å’"/>
+            <key code="13" output="∑"/>
+            <key code="14" output="´"/>
+            <key code="15" output="®"/>
+            <key code="16" output="Ã"/>
+            <key code="17" output="†"/>
+            <key code="18" output="¡"/>
+            <key code="19" output="â„¢"/>
+            <key code="20" output="£"/>
+            <key code="21" output="¢"/>
+            <key code="22" output="§"/>
+            <key code="23" output="∞"/>
+            <key code="24" output="≠"/>
+            <key code="25" output="ª"/>
+            <key code="26" output="¶"/>
+            <key code="27" output="–"/>
+            <key code="28" output="•"/>
+            <key code="29" output="º"/>
+            <key code="30" output="‘"/>
+            <key code="31" output="Ø"/>
+            <key code="32" output="¨"/>
+            <key code="33" output="“"/>
+            <key code="34" output="ˆ"/>
+            <key code="35" output="âˆ"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="Ã’"/>
+            <key code="38" output="Ô"/>
+            <key code="39" output="Æ"/>
+            <key code="40" output="Ëš"/>
+            <key code="41" output="…"/>
+            <key code="42" output="«"/>
+            <key code="43" output="≤"/>
+            <key code="44" output="÷"/>
+            <key code="45" output="˜"/>
+            <key code="46" output="Â"/>
+            <key code="47" output="≥"/>
+            <key code="48" output="&#x0009;"/>
+            <key code="49" output=" "/>
+            <key code="50" output="`"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="&#x001D;"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="&#x001C;"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="&#x001F;"/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="&#x001E;"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="6">
+            <key code="0" output="Ã¥"/>
+            <key code="1" output="ß"/>
+            <key code="2" output="∂"/>
+            <key code="3" output="Æ’"/>
+            <key code="4" output="Ë™"/>
+            <key code="5" output="©"/>
+            <key code="6" output="Ω"/>
+            <key code="7" output="≈"/>
+            <key code="8" output="ç"/>
+            <key code="9" output="√"/>
+            <key code="10" output="§"/>
+            <key code="11" output="∫"/>
+            <key code="12" output="Å“"/>
+            <key code="13" output="∑"/>
+            <key code="14" output="´"/>
+            <key code="15" output="®"/>
+            <key code="16" output="Â¥"/>
+            <key code="17" output="†"/>
+            <key code="18" output="¡"/>
+            <key code="19" output="â„¢"/>
+            <key code="20" output="£"/>
+            <key code="21" output="¢"/>
+            <key code="22" output="§"/>
+            <key code="23" output="∞"/>
+            <key code="24" output="≠"/>
+            <key code="25" output="ª"/>
+            <key code="26" output="¶"/>
+            <key code="27" output="–"/>
+            <key code="28" output="•"/>
+            <key code="29" output="º"/>
+            <key code="30" output="‘"/>
+            <key code="31" output="ø"/>
+            <key code="32" output="¨"/>
+            <key code="33" output="“"/>
+            <key code="34" output="^"/>
+            <key code="35" output="Ï€"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="¬"/>
+            <key code="38" output="∆"/>
+            <key code="39" output="æ"/>
+            <key code="40" output="Ëš"/>
+            <key code="41" output="…"/>
+            <key code="42" output="«"/>
+            <key code="43" output="≤"/>
+            <key code="44" output="÷"/>
+            <key code="45" output="~"/>
+            <key code="46" output="µ"/>
+            <key code="47" output="≥"/>
+            <key code="48" output="&#x0009;"/>
+            <key code="49" output=" "/>
+            <key code="50" output="`"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="&#x001D;"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="&#x001C;"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="&#x001F;"/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="&#x001E;"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="7">
+            <key code="0" output="&#x0001;"/>
+            <key code="1" output="&#x0013;"/>
+            <key code="2" output="&#x0004;"/>
+            <key code="3" output="&#x0006;"/>
+            <key code="4" output="&#x0008;"/>
+            <key code="5" output="&#x0007;"/>
+            <key code="6" output="&#x001A;"/>
+            <key code="7" output="&#x0018;"/>
+            <key code="8" output="&#x0003;"/>
+            <key code="9" output="&#x0016;"/>
+            <key code="10" output="0"/>
+            <key code="11" output="&#x0002;"/>
+            <key code="12" output="&#x0011;"/>
+            <key code="13" output="&#x0017;"/>
+            <key code="14" output="&#x0005;"/>
+            <key code="15" output="&#x0012;"/>
+            <key code="16" output="&#x0019;"/>
+            <key code="17" output="&#x0014;"/>
+            <key code="18" output="1"/>
+            <key code="19" output="2"/>
+            <key code="20" output="3"/>
+            <key code="21" output="4"/>
+            <key code="22" output="6"/>
+            <key code="23" output="5"/>
+            <key code="24" output="="/>
+            <key code="25" output="9"/>
+            <key code="26" output="7"/>
+            <key code="27" output="&#x001F;"/>
+            <key code="28" output="8"/>
+            <key code="29" output="0"/>
+            <key code="30" output="&#x001D;"/>
+            <key code="31" output="&#x000F;"/>
+            <key code="32" output="&#x0015;"/>
+            <key code="33" output="&#x001B;"/>
+            <key code="34" output="&#x0009;"/>
+            <key code="35" output="&#x0010;"/>
+            <key code="36" output="&#x000D;"/>
+            <key code="37" output="&#x000C;"/>
+            <key code="38" output="&#x000A;"/>
+            <key code="39" output="&#x0027;"/>
+            <key code="40" output="&#x000B;"/>
+            <key code="41" output=";"/>
+            <key code="42" output="&#x001C;"/>
+            <key code="43" output=","/>
+            <key code="44" output="/"/>
+            <key code="45" output="&#x000E;"/>
+            <key code="46" output="&#x000D;"/>
+            <key code="47" output="."/>
+            <key code="48" output="&#x0009;"/>
+            <key action="5" code="49"/>
+            <key code="50" output="`"/>
+            <key code="51" output="&#x0008;"/>
+            <key code="52" output="&#x0003;"/>
+            <key code="53" output="&#x001B;"/>
+            <key code="64" output="&#x0010;"/>
+            <key code="65" output="."/>
+            <key code="66" output="&#x001D;"/>
+            <key code="67" output="*"/>
+            <key code="69" output="+"/>
+            <key code="70" output="&#x001C;"/>
+            <key code="71" output="&#x001B;"/>
+            <key code="72" output="&#x001F;"/>
+            <key code="75" output="/"/>
+            <key code="76" output="&#x0003;"/>
+            <key code="77" output="&#x001E;"/>
+            <key code="78" output="-"/>
+            <key code="79" output="&#x0010;"/>
+            <key code="80" output="&#x0010;"/>
+            <key code="81" output="="/>
+            <key code="82" output="0"/>
+            <key code="83" output="1"/>
+            <key code="84" output="2"/>
+            <key code="85" output="3"/>
+            <key code="86" output="4"/>
+            <key code="87" output="5"/>
+            <key code="88" output="6"/>
+            <key code="89" output="7"/>
+            <key code="91" output="8"/>
+            <key code="92" output="9"/>
+            <key code="96" output="&#x0010;"/>
+            <key code="97" output="&#x0010;"/>
+            <key code="98" output="&#x0010;"/>
+            <key code="99" output="&#x0010;"/>
+            <key code="100" output="&#x0010;"/>
+            <key code="101" output="&#x0010;"/>
+            <key code="102" output="&#x0010;"/>
+            <key code="103" output="&#x0010;"/>
+            <key code="104" output="&#x0010;"/>
+            <key code="105" output="&#x0010;"/>
+            <key code="106" output="&#x0010;"/>
+            <key code="107" output="&#x0010;"/>
+            <key code="108" output="&#x0010;"/>
+            <key code="109" output="&#x0010;"/>
+            <key code="110" output="&#x0010;"/>
+            <key code="111" output="&#x0010;"/>
+            <key code="112" output="&#x0010;"/>
+            <key code="113" output="&#x0010;"/>
+            <key code="114" output="&#x0005;"/>
+            <key code="115" output="&#x0001;"/>
+            <key code="116" output="&#x000B;"/>
+            <key code="117" output="&#x007F;"/>
+            <key code="118" output="&#x0010;"/>
+            <key code="119" output="&#x0004;"/>
+            <key code="120" output="&#x0010;"/>
+            <key code="121" output="&#x000C;"/>
+            <key code="122" output="&#x0010;"/>
+            <key code="123" output="&#x001C;"/>
+            <key code="124" output="&#x001D;"/>
+            <key code="125" output="&#x001F;"/>
+            <key code="126" output="&#x001E;"/>
+        </keyMap>
+        <keyMap index="8" baseMapSet="16c" baseIndex="0">
+            <key code="18" output="!"/>
+            <key code="19" output="@"/>
+            <key code="20" output="#"/>
+            <key code="21" output="$"/>
+            <key code="22" output="^"/>
+            <key code="23" output="%"/>
+            <key code="25" output="("/>
+            <key code="26" output="&#x0026;"/>
+            <key code="27" output="_"/>
+            <key code="28" output="*"/>
+            <key code="29" output=")"/>
+            <key code="30" output="}"/>
+            <key code="33" output="{"/>
+            <key code="42" output="|"/>
+        </keyMap>
+        <keyMap index="9" baseMapSet="16c" baseIndex="1">
+            <key code="18" output="1"/>
+            <key code="19" output="2"/>
+            <key code="20" output="3"/>
+            <key code="21" output="4"/>
+            <key code="22" output="6"/>
+            <key code="23" output="5"/>
+            <key code="25" output="9"/>
+            <key code="26" output="7"/>
+            <key code="27" output="-"/>
+            <key code="28" output="8"/>
+            <key code="29" output="0"/>
+            <key code="30" output="]"/>
+            <key code="33" output="["/>
+            <key code="42" output="\"/>
+        </keyMap>
+    </keyMapSet>
+    <keyMapSet id="994">
+        <keyMap baseIndex="0" baseMapSet="16c" index="0">
+            <key code="24" output="^"/>
+            <key code="30" output="["/>
+            <key code="33" output="@"/>
+            <key code="39" output=":"/>
+            <key code="42" output="]"/>
+            <key code="93" output="Â¥"/>
+            <key code="94" output="_"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+        <keyMap baseIndex="1" baseMapSet="16c" index="1">
+            <key code="19" output="&#x0022;"/>
+            <key code="22" output="&#x0026;"/>
+            <key code="24" output="~"/>
+            <key code="25" output=")"/>
+            <key code="26" output="&#x0027;"/>
+            <key code="27" output="="/>
+            <key code="28" output="("/>
+            <key code="29" output="0"/>
+            <key code="30" output="{"/>
+            <key code="33" output="`"/>
+            <key code="39" output="*"/>
+            <key code="41" output="+"/>
+            <key code="42" output="}"/>
+            <key code="93" output="|"/>
+            <key code="94" output="_"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+        <keyMap baseIndex="2" baseMapSet="16c" index="2">
+            <key code="24" output="^"/>
+            <key code="30" output="["/>
+            <key code="33" output="@"/>
+            <key code="39" output=":"/>
+            <key code="42" output="]"/>
+            <key code="93" output="Â¥"/>
+            <key code="94" output="_"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+        <keyMap baseIndex="3" baseMapSet="16c" index="3">
+            <key code="93" output="\"/>
+            <key action="1" code="94"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+        <keyMap baseIndex="4" baseMapSet="16c" index="4">
+            <key code="93" output="|"/>
+            <key code="94" output="`"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+        <keyMap baseIndex="5" baseMapSet="16c" index="5">
+            <key code="93" output="\"/>
+            <key code="94" output="`"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+        <keyMap baseIndex="6" baseMapSet="16c" index="6">
+            <key code="93" output="\"/>
+            <key code="94" output="_"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+        <keyMap baseIndex="7" baseMapSet="16c" index="7">
+            <key code="93" output="|"/>
+            <key code="94" output="_"/>
+            <key code="95" output=","/>
+            <key action="5" code="102"/>
+            <key action="5" code="104"/>
+        </keyMap>
+    </keyMapSet>
+    <actions>
+        <action id="0">
+            <when next="s1" state="none"/>
+        </action>
+        <action id="1">
+            <when next="s2" state="none"/>
+        </action>
+        <action id="10">
+            <when output="O" state="none"/>
+            <when output="Ó" state="s1"/>
+            <when output="Ã’" state="s2"/>
+            <when output="Ô" state="s3"/>
+            <when output="Ö" state="s4"/>
+            <when output="Õ" state="s5"/>
+        </action>
+        <action id="11">
+            <when output="U" state="none"/>
+            <when output="Ú" state="s1"/>
+            <when output="Ù" state="s2"/>
+            <when output="Û" state="s3"/>
+            <when output="Ü" state="s4"/>
+        </action>
+        <action id="12">
+            <when output="Y" state="none"/>
+            <when output="Ÿ" state="s4"/>
+        </action>
+        <action id="13">
+            <when output="a" state="none"/>
+            <when output="á" state="s1"/>
+            <when output="à" state="s2"/>
+            <when output="â" state="s3"/>
+            <when output="ä" state="s4"/>
+            <when output="ã" state="s5"/>
+        </action>
+        <action id="14">
+            <when output="e" state="none"/>
+            <when output="é" state="s1"/>
+            <when output="è" state="s2"/>
+            <when output="ê" state="s3"/>
+            <when output="ë" state="s4"/>
+        </action>
+        <action id="15">
+            <when output="i" state="none"/>
+            <when output="í" state="s1"/>
+            <when output="ì" state="s2"/>
+            <when output="î" state="s3"/>
+            <when output="ï" state="s4"/>
+        </action>
+        <action id="16">
+            <when output="n" state="none"/>
+            <when output="ñ" state="s5"/>
+        </action>
+        <action id="17">
+            <when output="o" state="none"/>
+            <when output="ó" state="s1"/>
+            <when output="ò" state="s2"/>
+            <when output="ô" state="s3"/>
+            <when output="ö" state="s4"/>
+            <when output="õ" state="s5"/>
+        </action>
+        <action id="18">
+            <when output="u" state="none"/>
+            <when output="ú" state="s1"/>
+            <when output="ù" state="s2"/>
+            <when output="û" state="s3"/>
+            <when output="ü" state="s4"/>
+        </action>
+        <action id="19">
+            <when output="y" state="none"/>
+            <when output="ÿ" state="s4"/>
+        </action>
+        <action id="2">
+            <when next="s3" state="none"/>
+        </action>
+        <action id="3">
+            <when next="s4" state="none"/>
+        </action>
+        <action id="4">
+            <when next="s5" state="none"/>
+        </action>
+        <action id="5">
+            <when output=" " state="none"/>
+            <when output="´" state="s1"/>
+            <when output="`" state="s2"/>
+            <when output="ˆ" state="s3"/>
+            <when output="¨" state="s4"/>
+            <when output="˜" state="s5"/>
+        </action>
+        <action id="6">
+            <when output="A" state="none"/>
+            <when output="Ã" state="s1"/>
+            <when output="À" state="s2"/>
+            <when output="Â" state="s3"/>
+            <when output="Ä" state="s4"/>
+            <when output="Ã" state="s5"/>
+        </action>
+        <action id="7">
+            <when output="E" state="none"/>
+            <when output="É" state="s1"/>
+            <when output="È" state="s2"/>
+            <when output="Ê" state="s3"/>
+            <when output="Ë" state="s4"/>
+        </action>
+        <action id="8">
+            <when output="I" state="none"/>
+            <when output="Ã" state="s1"/>
+            <when output="Ì" state="s2"/>
+            <when output="ÃŽ" state="s3"/>
+            <when output="Ã" state="s4"/>
+        </action>
+        <action id="9">
+            <when output="N" state="none"/>
+            <when output="Ñ" state="s5"/>
+        </action>
+    </actions>
+    <terminators>
+        <when output="´" state="s1"/>
+        <when output="`" state="s2"/>
+        <when output="ˆ" state="s3"/>
+        <when output="¨" state="s4"/>
+        <when output="˜" state="s5"/>
+    </terminators>
+</keyboard>
diff --git a/etc/Dark.terminal b/etc/Dark.terminal
new file mode 100644
index 00000000..75184f05
--- /dev/null
+++ b/etc/Dark.terminal
@@ -0,0 +1,1652 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ANSIBlackColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECswLjA4NjQxNDgyMTQ1IDAuMDgyNjczMjQ0MTggMC4wNjE3
+	NjQxODgxMSAxTxApMC4wNjg1NjU0ODc4NiAwLjA2NjU1MDExMzI2IDAuMDUzMTg5MzQ0
+	NwAQAYACgAXTGBkRGhscVE5TSURVTlNJQ0MQB4ADgARPEQxIAAAMSExpbm8CEAAAbW50
+	clJHQiBYWVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAA
+	AAAAAPbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAU
+	YmtwdAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1u
+	ZAAAAlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAA
+	A/gAAAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwA
+	AAgMYlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1Q
+	YWNrYXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAA
+	AAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAA
+	AAAAAAAAAAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABja
+	WFlaIAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMu
+	Y2gAAAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2
+	LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVD
+	IDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlv
+	biBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25k
+	aXRpb24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3
+	AAAAAAATpP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf
+	521lYXMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1
+	cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4A
+	YwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDg
+	AOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwB
+	gwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJU
+	Al0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oD
+	ZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSo
+	BLYExATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicG
+	NwZIBlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4
+	CAsIHwgyCEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsK
+	EQonCj0KVApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxc
+	DHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4P
+	CQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHo
+	EgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIV
+	NBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihiv
+	GNUY+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHsc
+	oxzMHPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDE
+	IPAhHCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTgl
+	aCWXJccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1
+	KmgqmyrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ov
+	kS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUT
+	NU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87
+	LTtrO6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFq
+	QaxB7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVI
+	S0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9J
+	T5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW
+	91dEV5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69
+	Xw9fYV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhn
+	PWeTZ+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/R
+	cCtwhnDgcTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5
+	KnmJeed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKS
+	gvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOM
+	yo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cK
+	l3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobai
+	JqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1E
+	rbiuLa6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5
+	SrnCuju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVL
+	xcjGRsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7S
+	P9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p
+	36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77Ibt
+	Ee2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn
+	+3f8B/yY/Sn9uv5L/tz/bf//0h8gISJaJGNsYXNzbmFtZVgkY2xhc3Nlc1xOU0NvbG9y
+	U3BhY2WiIyRcTlNDb2xvclNwYWNlWE5TT2JqZWN00h8gJidXTlNDb2xvcqImJAAIABEA
+	GgAkACkAMgA3AEkATABRAFMAWgBgAGsAeAB+AIsAoACnANUBAQEDAQUBBwEOARMBGQEb
+	AR0BHw1rDXANew2EDZENlA2hDaoNrw23AAAAAAAAAgEAAAAAAAAAKAAAAAAAAAAAAAAA
+	AAAADbo=
+	</data>
+	<key>ANSIBlueColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjIzNzg3NzEzMDUgMC4zODQ0ODYzMTc2IDAuNDAxODE3
+	NTYwMiAxTxAnMC4xODUxNzgwMTE3IDAuMzEyNjgzODIwNyAwLjMyNzM1MzE0OTcAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSIBrightBlackColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjI5ODc1MjYwNTkgMC4yNzU0NDMxMzY3IDAuMjA4Mjg5
+	OTIxMyAxTxAnMC4yMzI1NTg4MTY3IDAuMjEzOTgzMDU4OSAwLjE1NzM3MjYyMzcAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSIBrightBlueColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjI5OTI5MDg5NTUgMC40ODI3MTYzODE1IDAuNDk2MTAy
+	ODA5OSAxTxAnMC4yMzg5NDMwNzAyIDAuNDA5NTA4Mzc3MyAwLjQyMDQxODk3NzcAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSIBrightCyanColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjQxODI5MzY1NDkgMC41OTkyNjI5NTI4IDAuNDIxMTYz
+	NDY5NiAxTxAnMC4zNDk1MDUyMTU5IDAuNTM3MzI0Nzg2MiAwLjM0NjU0MzYzOTkAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSIBrightGreenColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjU1NjU1MTQ1NjUgMC42MDA4OTg1NjM5IDAuMTE2MjQx
+	OTY5MiAxTxAoMC40ODUyMTc3NTAxIDAuNTQxMTE2ODkzMyAwLjA5MjAwNzkyMDE1ABAB
+	gAKABdMYGREaGxxUTlNJRFVOU0lDQxAHgAOABE8RDEgAAAxITGlubwIQAABtbnRyUkdC
+	IFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA
+	9tYAAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0
+	AAACBAAAABRyWFlaAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAAC
+	VAAAAHBkbWRkAAACxAAAAIh2dWVkAAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD+AAA
+	ABRtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJDAAAEPAAACAxnVFJDAAAEPAAACAxi
+	VFJDAAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBhY2th
+	cmQgQ29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAA
+	ABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAA
+	AAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVog
+	AAAAAAAAJKAAAA+EAAC2z2Rlc2MAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAA
+	AAAAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC5JRUMgNjE5NjYtMi4x
+	IERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5
+	NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGlu
+	IElFQzYxOTY2LTIuMQAAAAAAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlv
+	biBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZpZXcAAAAA
+	ABOk/gAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAAVx/nbWVh
+	cwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAA
+	AAAAAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgA
+	bQByAHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDr
+	APAA9gD7AQEBBwENARMBGQEfASUBKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsB
+	kgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJn
+	AnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMhAy0DOANDA08DWgNmA3ID
+	fgOKA5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH4EjASaBKgEtgTE
+	BNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3BkgG
+	WQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICwgf
+	CDIIRghaCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicK
+	PQpUCmoKgQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyO
+	DKcMwAzZDPMNDQ0mDUANWg10DY4NqQ3DDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUP
+	QQ9eD3oPlg+zD88P7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxIm
+	EkUSZBKEEqMSwxLjEwMTIxNDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYV
+	eBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6
+	GSAZRRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc
+	9R0eHUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4faR+UH78f6iAVIEEgbCCYIMQg8CEc
+	IUghdSGhIc4h+yInIlUigiKvIt0jCiM4I2YjlCPCI/AkHyRNJHwkqyTaJQklOCVoJZcl
+	xyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYpOClrKZ0p0CoCKjUqaCqb
+	Ks8rAis2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQvWi+RL8cv
+	/jA1MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1TTWH
+	NcI1/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7
+	qjvoPCc8ZTykPOM9Ij1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHu
+	QjBCckK1QvdDOkN9Q8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI
+	10kdSWNJqUnwSjdKfUrESwxLU0uaS+JMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0/d
+	UCdQcVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVVwlYPVlxWqVb3V0RX
+	klfgWC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5sXr1fD19h
+	X7NgBWBXYKpg/GFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn
+	6Wg/aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CG
+	cOBxOnGVcfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl5
+	53pGeqV7BHtje8J8IXyBfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INX
+	g7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ/opkisqLMIuWi/yMY4zKjTGN
+	mI3/jmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmWNJaflwqXdZfg
+	mEyYuJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDYoUehtqImopaj
+	BqN2o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+rAqt1q+msXKzQrUStuK4t
+	rqGvFq+LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6
+	O7q1uy67p7whvJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvFyMZG
+	xsPHQce/yD3IvMk6ybnKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHT
+	RNPG1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A2
+	4L3hROHM4lPi2+Nj4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ6lvq5etw6/vshu0R7Zzu
+	KO6070DvzPBY8OXxcvH/8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH
+	/Jj9Kf26/kv+3P9t///SHyAhIlokY2xhc3NuYW1lWCRjbGFzc2VzXE5TQ29sb3JTcGFj
+	ZaIjJFxOU0NvbG9yU3BhY2VYTlNPYmplY3TSHyAmJ1dOU0NvbG9yoiYkAAgAEQAaACQA
+	KQAyADcASQBMAFEAUwBaAGAAawB4AH4AiwCgAKcA0gD9AP8BAQEDAQoBDwEVARcBGQEb
+	DWcNbA13DYANjQ2QDZ0Npg2rDbMAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAN
+	tg==
+	</data>
+	<key>ANSIBrightMagentaColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjYwMDY0NDIzMDggMC4zNTgyNDcxNjA5IDAuNDE4NDg3
+	MzEwNCAxTxAnMC41MjUyNzc3OTM0IDAuMjc3OTIxMzc4NiAwLjM0MzkxMTY3NzYAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSIBrightRedColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECkwLjgwMDg5NjQ2NTggMC4xOTc5Nzc1NDI5IDAuMDc4OTg3
+	MTU4ODMgMU8QKDAuNzQ2NjI0MTEyMSAwLjExOTYyMTgwNTggMC4wNjg5MzI5ODc3NQAQ
+	AYACgAXTGBkRGhscVE5TSURVTlNJQ0MQB4ADgARPEQxIAAAMSExpbm8CEAAAbW50clJH
+	QiBYWVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAA
+	APbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtw
+	dAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAA
+	AlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gA
+	AAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwAAAgM
+	YlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNr
+	YXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAA
+	AAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAA
+	AAAAAAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFla
+	IAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gA
+	AAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2LTIu
+	MSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYx
+	OTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBp
+	biBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRp
+	b24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAA
+	AAATpP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521l
+	YXMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYA
+	AAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBo
+	AG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA
+	6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGL
+	AZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0C
+	ZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oDZgNy
+	A34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYE
+	xATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZI
+	BlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsI
+	HwgyCEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQon
+	Cj0KVApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUM
+	jgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8l
+	D0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHoEgcS
+	JhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIVNBVW
+	FXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY
+	+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzM
+	HPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAh
+	HCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWX
+	Jccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1Kmgq
+	myrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/H
+	L/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01
+	hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtr
+	O6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB
+	7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iR
+	SNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP
+	3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dE
+	V5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9f
+	YV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeT
+	Z+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtw
+	hnDgcTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJ
+	eed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSD
+	V4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOMyo0x
+	jZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cKl3WX
+	4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobaiJqKW
+	owajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1Erbiu
+	La6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnC
+	uju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjG
+	RsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB
+	00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/g
+	NuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c
+	7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8
+	B/yY/Sn9uv5L/tz/bf//0h8gISJaJGNsYXNzbmFtZVgkY2xhc3Nlc1xOU0NvbG9yU3Bh
+	Y2WiIyRcTlNDb2xvclNwYWNlWE5TT2JqZWN00h8gJidXTlNDb2xvcqImJAAIABEAGgAk
+	ACkAMgA3AEkATABRAFMAWgBgAGsAeAB+AIsAoACnANMA/gEAAQIBBAELARABFgEYARoB
+	HA1oDW0NeA2BDY4NkQ2eDacNrA20AAAAAAAAAgEAAAAAAAAAKAAAAAAAAAAAAAAAAAAA
+	Dbc=
+	</data>
+	<key>ANSIBrightWhiteColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjgwMTk4NTU2MTggMC43MzU3NzAwNDY3IDAuNTU1MDUz
+	NTMyMSAxTxAnMC43NTY0MTcxNTUzIDAuNjg1MjI5MjQxOCAwLjQ4MjY3MjM5MzMAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSIBrightYellowColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjgwMTIwNzQyMzIgMC41ODM2NjYxNDU4IDAuMTU3Mjcw
+	OTk3OCAxTxAnMC43NTIwNzE5NzY3IDAuNTE1MzE4NzUxMyAwLjEyMjE5NTczNTYAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSICyanColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECcwLjMzMzEyNjMwNjUgMC40NzcwOTI5ODEzIDAuMzMyMDk3
+	ODg4IDFPECcwLjI2ODExMDA5NjUgMC40MDc4NTk0NDQ2IDAuMjYyOTM4MDIyNgAQAYAC
+	gAXTGBkRGhscVE5TSURVTlNJQ0MQB4ADgARPEQxIAAAMSExpbm8CEAAAbW50clJHQiBY
+	WVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAAAPbW
+	AAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAA
+	AgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAAAlQA
+	AABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gAAAAU
+	bWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwAAAgMYlRS
+	QwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNrYXJk
+	IENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAS
+	c1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAA
+	AAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAA
+	AAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAA
+	AAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2LTIuMSBE
+	ZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYxOTY2
+	LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJ
+	RUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24g
+	aW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAAAAAT
+	pP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521lYXMA
+	AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYAAAAA
+	AAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0A
+	cgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA6wDw
+	APYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGLAZIB
+	mgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0CZwJx
+	AnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oDZgNyA34D
+	igOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYExATT
+	BOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZIBlkG
+	agZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgy
+	CEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0K
+	VApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgyn
+	DMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EP
+	Xg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHoEgcSJhJF
+	EmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIVNBVWFXgV
+	mxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY+hkg
+	GUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzMHPUd
+	Hh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFI
+	IXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWXJccl
+	9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1KmgqmyrP
+	KwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/HL/4w
+	NTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01hzXC
+	Nf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtrO6o7
+	6DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB7kIw
+	QnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iRSNdJ
+	HUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP3VAn
+	UHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dEV5JX
+	4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9fYV+z
+	YAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeTZ+lo
+	P2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDg
+	cTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6
+	RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6
+	hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOMyo0xjZiN
+	/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cKl3WX4JhM
+	mLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobaiJqKWowaj
+	dqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1ErbiuLa6h
+	rxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6
+	tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjGRsbD
+	x0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TT
+	xtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/gNuC9
+	4UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c7iju
+	tO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8B/yY
+	/Sn9uv5L/tz/bf//0h8gISJaJGNsYXNzbmFtZVgkY2xhc3Nlc1xOU0NvbG9yU3BhY2Wi
+	IyRcTlNDb2xvclNwYWNlWE5TT2JqZWN00h8gJidXTlNDb2xvcqImJAAIABEAGgAkACkA
+	MgA3AEkATABRAFMAWgBgAGsAeAB+AIsAoACnANEA+wD9AP8BAQEIAQ0BEwEVARcBGQ1l
+	DWoNdQ1+DYsNjg2bDaQNqQ2xAAAAAAAAAgEAAAAAAAAAKAAAAAAAAAAAAAAAAAAADbQ=
+	</data>
+	<key>ANSIGreenColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECkwLjQ0NjkyMDM5NDkgMC40NzgzODYyMjMzIDAuMDkzNTM1
+	OTM3MzcgMU8QKDAuMzcyNzA2MDU1NiAwLjQxMDYwNDExOTMgMC4wNzU3MTQ2MzI4NwAQ
+	AYACgAXTGBkRGhscVE5TSURVTlNJQ0MQB4ADgARPEQxIAAAMSExpbm8CEAAAbW50clJH
+	QiBYWVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAA
+	APbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtw
+	dAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAA
+	AlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gA
+	AAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwAAAgM
+	YlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNr
+	YXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAA
+	AAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAA
+	AAAAAAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFla
+	IAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gA
+	AAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2LTIu
+	MSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYx
+	OTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBp
+	biBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRp
+	b24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAA
+	AAATpP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521l
+	YXMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYA
+	AAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBo
+	AG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA
+	6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGL
+	AZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0C
+	ZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oDZgNy
+	A34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYE
+	xATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZI
+	BlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsI
+	HwgyCEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQon
+	Cj0KVApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUM
+	jgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8l
+	D0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHoEgcS
+	JhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIVNBVW
+	FXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY
+	+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzM
+	HPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAh
+	HCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWX
+	Jccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1Kmgq
+	myrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/H
+	L/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01
+	hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtr
+	O6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB
+	7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iR
+	SNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP
+	3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dE
+	V5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9f
+	YV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeT
+	Z+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtw
+	hnDgcTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJ
+	eed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSD
+	V4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOMyo0x
+	jZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cKl3WX
+	4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobaiJqKW
+	owajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1Erbiu
+	La6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnC
+	uju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjG
+	RsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB
+	00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/g
+	NuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c
+	7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8
+	B/yY/Sn9uv5L/tz/bf//0h8gISJaJGNsYXNzbmFtZVgkY2xhc3Nlc1xOU0NvbG9yU3Bh
+	Y2WiIyRcTlNDb2xvclNwYWNlWE5TT2JqZWN00h8gJidXTlNDb2xvcqImJAAIABEAGgAk
+	ACkAMgA3AEkATABRAFMAWgBgAGsAeAB+AIsAoACnANMA/gEAAQIBBAELARABFgEYARoB
+	HA1oDW0NeA2BDY4NkQ2eDacNrA20AAAAAAAAAgEAAAAAAAAAKAAAAAAAAAAAAAAAAAAA
+	Dbc=
+	</data>
+	<key>ANSIMagentaColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjQ3ODEyOTQ0NjUgMC4yODgyOTk1NjA1IDAuMzMyMzUx
+	ODMzNiAxTxAnMC4zOTg3NjkxNDAyIDAuMjE3NjQ0NzUxMSAwLjI2MzEzMjE4NDcAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>ANSIRedColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECkwLjYzODQyMzk3OTMgMC4xNTYyMTk5NTkzIDAuMDYzNTUz
+	ODE3NTcgMU8QKTAuNTYzOTM3NzgzMiAwLjA5NTk2MjQ3OTcxIDAuMDU3NzQ0NjQ0NTgA
+	EAGAAoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJS
+	R0IgWFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAA
+	AAD21gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJr
+	cHQAAAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQA
+	AAJUAAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4
+	AAAAFG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAI
+	DGJUUkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFj
+	a2FyZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAA
+	AAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAA
+	AAAAAAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZ
+	WiAAAAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNo
+	AAAAAAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0y
+	LjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2
+	MTk2Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24g
+	aW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0
+	aW9uIGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAA
+	AAAAE6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dt
+	ZWFzAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2
+	AAAAAAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMA
+	aABtAHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADl
+	AOsA8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMB
+	iwGSAZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJd
+	AmcCcQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YD
+	cgN+A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2
+	BMQE0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcG
+	SAZZBmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgL
+	CB8IMghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEK
+	Jwo9ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1
+	DI4MpwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkP
+	JQ9BD14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIH
+	EiYSRRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQV
+	VhV4FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjV
+	GPoZIBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMc
+	zBz1HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDw
+	IRwhSCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgl
+	lyXHJfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpo
+	KpsqzysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Ev
+	xy/+MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVN
+	NYc1wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07
+	azuqO+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGs
+	Qe5CMEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtI
+	kUjXSR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+T
+	T91QJ1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdX
+	RFeSV+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8P
+	X2Ffs2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1n
+	k2fpaD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XAr
+	cIZw4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5
+	iXnnekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0
+	g1eDuoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqN
+	MY2Yjf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1
+	l+CYTJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiai
+	lqMGo3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24
+	ri2uoa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5
+	wro7urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XI
+	xkbGw8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/S
+	wdNE08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v
+	4DbgveFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHt
+	nO4o7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3
+	/Af8mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNw
+	YWNloiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoA
+	JAApADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDTAP8BAQEDAQUBDAERARcBGQEb
+	AR0NaQ1uDXkNgg2PDZINnw2oDa0NtQAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAA
+	AA24
+	</data>
+	<key>ANSIWhiteColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjYwMTQyMTM1NjIgMC41NTQ3NzkxNzE5IDAuNDIwMzc2
+	ODM3MyAxTxAmMC41MzAyMTU0NDIyIDAuNDg0NTIxOTI1NCAwLjM0NjA2NTQwMgAQAYAC
+	gAXTGBkRGhscVE5TSURVTlNJQ0MQB4ADgARPEQxIAAAMSExpbm8CEAAAbW50clJHQiBY
+	WVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAAAPbW
+	AAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtwdAAA
+	AgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAAAlQA
+	AABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gAAAAU
+	bWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwAAAgMYlRS
+	QwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNrYXJk
+	IENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAS
+	c1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAAAAAA
+	AAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAA
+	AAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAA
+	AAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2LTIuMSBE
+	ZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYxOTY2
+	LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbiBJ
+	RUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24g
+	aW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAAAAAT
+	pP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521lYXMA
+	AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYAAAAA
+	AAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBoAG0A
+	cgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA6wDw
+	APYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGLAZIB
+	mgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0CZwJx
+	AnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oDZgNyA34D
+	igOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYExATT
+	BOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZIBlkG
+	agZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsIHwgy
+	CEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQonCj0K
+	VApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUMjgyn
+	DMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8lD0EP
+	Xg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHoEgcSJhJF
+	EmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIVNBVWFXgV
+	mxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY+hkg
+	GUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzMHPUd
+	Hh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAhHCFI
+	IXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWXJccl
+	9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1KmgqmyrP
+	KwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/HL/4w
+	NTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01hzXC
+	Nf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtrO6o7
+	6DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB7kIw
+	QnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iRSNdJ
+	HUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP3VAn
+	UHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dEV5JX
+	4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9fYV+z
+	YAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeTZ+lo
+	P2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtwhnDg
+	cTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJeed6
+	RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSDV4O6
+	hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOMyo0xjZiN
+	/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cKl3WX4JhM
+	mLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobaiJqKWowaj
+	dqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1ErbiuLa6h
+	rxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnCuju6
+	tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjGRsbD
+	x0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB00TT
+	xtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/gNuC9
+	4UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c7iju
+	tO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8B/yY
+	/Sn9uv5L/tz/bf//0h8gISJaJGNsYXNzbmFtZVgkY2xhc3Nlc1xOU0NvbG9yU3BhY2Wi
+	IyRcTlNDb2xvclNwYWNlWE5TT2JqZWN00h8gJidXTlNDb2xvcqImJAAIABEAGgAkACkA
+	MgA3AEkATABRAFMAWgBgAGsAeAB+AIsAoACnANIA+wD9AP8BAQEIAQ0BEwEVARcBGQ1l
+	DWoNdQ1+DYsNjg2bDaQNqQ2xAAAAAAAAAgEAAAAAAAAAKAAAAAAAAAAAAAAAAAAADbQ=
+	</data>
+	<key>ANSIYellowColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjYzOTQxMzA1ODggMC40NjU0MDE4MjgzIDAuMTI1ODc5
+	NzM0OCAxTxAoMC41Njg4Njk1OTA4IDAuMzkyMjI2OTY0MiAwLjA5ODMyNTU2NTQ2ABAB
+	gAKABdMYGREaGxxUTlNJRFVOU0lDQxAHgAOABE8RDEgAAAxITGlubwIQAABtbnRyUkdC
+	IFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA
+	9tYAAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0
+	AAACBAAAABRyWFlaAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAAC
+	VAAAAHBkbWRkAAACxAAAAIh2dWVkAAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD+AAA
+	ABRtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJDAAAEPAAACAxnVFJDAAAEPAAACAxi
+	VFJDAAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBhY2th
+	cmQgQ29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAA
+	ABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAA
+	AAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVog
+	AAAAAAAAJKAAAA+EAAC2z2Rlc2MAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAA
+	AAAAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC5JRUMgNjE5NjYtMi4x
+	IERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5
+	NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGlu
+	IElFQzYxOTY2LTIuMQAAAAAAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlv
+	biBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZpZXcAAAAA
+	ABOk/gAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAAVx/nbWVh
+	cwAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAA
+	AAAAAAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgA
+	bQByAHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDr
+	APAA9gD7AQEBBwENARMBGQEfASUBKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsB
+	kgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJn
+	AnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMhAy0DOANDA08DWgNmA3ID
+	fgOKA5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH4EjASaBKgEtgTE
+	BNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3BkgG
+	WQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICwgf
+	CDIIRghaCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicK
+	PQpUCmoKgQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyO
+	DKcMwAzZDPMNDQ0mDUANWg10DY4NqQ3DDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUP
+	QQ9eD3oPlg+zD88P7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxIm
+	EkUSZBKEEqMSwxLjEwMTIxNDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYV
+	eBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6
+	GSAZRRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc
+	9R0eHUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4faR+UH78f6iAVIEEgbCCYIMQg8CEc
+	IUghdSGhIc4h+yInIlUigiKvIt0jCiM4I2YjlCPCI/AkHyRNJHwkqyTaJQklOCVoJZcl
+	xyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYpOClrKZ0p0CoCKjUqaCqb
+	Ks8rAis2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQvWi+RL8cv
+	/jA1MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1TTWH
+	NcI1/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7
+	qjvoPCc8ZTykPOM9Ij1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHu
+	QjBCckK1QvdDOkN9Q8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI
+	10kdSWNJqUnwSjdKfUrESwxLU0uaS+JMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0/d
+	UCdQcVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVVwlYPVlxWqVb3V0RX
+	klfgWC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5sXr1fD19h
+	X7NgBWBXYKpg/GFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn
+	6Wg/aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CG
+	cOBxOnGVcfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl5
+	53pGeqV7BHtje8J8IXyBfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INX
+	g7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ/opkisqLMIuWi/yMY4zKjTGN
+	mI3/jmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmWNJaflwqXdZfg
+	mEyYuJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDYoUehtqImopaj
+	BqN2o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+rAqt1q+msXKzQrUStuK4t
+	rqGvFq+LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6
+	O7q1uy67p7whvJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvFyMZG
+	xsPHQce/yD3IvMk6ybnKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHT
+	RNPG1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A2
+	4L3hROHM4lPi2+Nj4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ6lvq5etw6/vshu0R7Zzu
+	KO6070DvzPBY8OXxcvH/8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH
+	/Jj9Kf26/kv+3P9t///SHyAhIlokY2xhc3NuYW1lWCRjbGFzc2VzXE5TQ29sb3JTcGFj
+	ZaIjJFxOU0NvbG9yU3BhY2VYTlNPYmplY3TSHyAmJ1dOU0NvbG9yoiYkAAgAEQAaACQA
+	KQAyADcASQBMAFEAUwBaAGAAawB4AH4AiwCgAKcA0gD9AP8BAQEDAQoBDwEVARcBGQEb
+	DWcNbA13DYANjQ2QDZ0Npg2rDbMAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAAN
+	tg==
+	</data>
+	<key>BackgroundColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECswLjA3ODU3MTg5MzI3IDAuMDc0ODI3NTQ0MzkgMC4wNTM5
+	MTM1MTEzNCAxTxApMC4wNjM1NDA2MzAwNCAwLjA2MTU1OTQwODkgMC4wNDg0NzkxODQ1
+	MQAQAYACgAXTGBkRGhscVE5TSURVTlNJQ0MQB4ADgARPEQxIAAAMSExpbm8CEAAAbW50
+	clJHQiBYWVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAA
+	AAAAAPbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAU
+	YmtwdAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1u
+	ZAAAAlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAA
+	A/gAAAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwA
+	AAgMYlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1Q
+	YWNrYXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAA
+	AAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAA
+	AAAAAAAAAAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABja
+	WFlaIAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMu
+	Y2gAAAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2
+	LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVD
+	IDYxOTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlv
+	biBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25k
+	aXRpb24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3
+	AAAAAAATpP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf
+	521lYXMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1
+	cnYAAAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4A
+	YwBoAG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDg
+	AOUA6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwB
+	gwGLAZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJU
+	Al0CZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oD
+	ZgNyA34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSo
+	BLYExATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicG
+	NwZIBlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4
+	CAsIHwgyCEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsK
+	EQonCj0KVApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxc
+	DHUMjgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4P
+	CQ8lD0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHo
+	EgcSJhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIV
+	NBVWFXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihiv
+	GNUY+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHsc
+	oxzMHPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDE
+	IPAhHCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTgl
+	aCWXJccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1
+	KmgqmyrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ov
+	kS/HL/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUT
+	NU01hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87
+	LTtrO6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFq
+	QaxB7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVI
+	S0iRSNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9J
+	T5NP3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW
+	91dEV5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69
+	Xw9fYV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhn
+	PWeTZ+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/R
+	cCtwhnDgcTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5
+	KnmJeed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKS
+	gvSDV4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOM
+	yo0xjZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cK
+	l3WX4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobai
+	JqKWowajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1E
+	rbiuLa6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5
+	SrnCuju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVL
+	xcjGRsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7S
+	P9LB00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p
+	36/gNuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77Ibt
+	Ee2c7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn
+	+3f8B/yY/Sn9uv5L/tz/bf//0h8gISJaJGNsYXNzbmFtZVgkY2xhc3Nlc1xOU0NvbG9y
+	U3BhY2WiIyRcTlNDb2xvclNwYWNlWE5TT2JqZWN00h8gJidXTlNDb2xvcqImJAAIABEA
+	GgAkACkAMgA3AEkATABRAFMAWgBgAGsAeAB+AIsAoACnANUBAQEDAQUBBwEOARMBGQEb
+	AR0BHw1rDXANew2EDZENlA2hDaoNrw23AAAAAAAAAgEAAAAAAAAAKAAAAAAAAAAAAAAA
+	AAAADbo=
+	</data>
+	<key>Bell</key>
+	<false/>
+	<key>BellBounceCritical</key>
+	<false/>
+	<key>CursorColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjQ3OTUyNTg2NDEgMC40NDQ2OTg0ODI4IDAuMzMxMzI2
+	MjQ2MyAxTxAnMC40MDMyNjEwNjU1IDAuMzcxNzA4MDk1MSAwLjI2MjQ2MDc2ODIAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>DisableANSIColor</key>
+	<false/>
+	<key>Font</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGkCwwVFlUkbnVsbNQNDg8QERIT
+	FFZOU1NpemVYTlNmRmxhZ3NWTlNOYW1lViRjbGFzcyNAJgAAAAAAABAQgAKAA1ZHb01v
+	bm/SFxgZGlokY2xhc3NuYW1lWCRjbGFzc2VzVk5TRm9udKIZG1hOU09iamVjdAgRGiQp
+	MjdJTFFTWF5nbnd+hY6QkpSboKu0u74AAAAAAAABAQAAAAAAAAAcAAAAAAAAAAAAAAAA
+	AAAAxw==
+	</data>
+	<key>FontAntialias</key>
+	<true/>
+	<key>FontHeightSpacing</key>
+	<integer>1</integer>
+	<key>FontWidthSpacing</key>
+	<integer>1</integer>
+	<key>ProfileCurrentVersion</key>
+	<real>2.0699999999999998</real>
+	<key>SelectionColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECkwLjYzNzg1MDc2MTQgMC4yNTM4NjgzNzEyIDAuMDYwOTk5
+	MzExNTEgMU8QKDAuNTY0MDcwNzAxNiAwLjE4NDY3ODM2MDggMC4wNTY1MzkxODUzNQAQ
+	AYACgAXTGBkRGhscVE5TSURVTlNJQ0MQB4ADgARPEQxIAAAMSExpbm8CEAAAbW50clJH
+	QiBYWVogB84AAgAJAAYAMQAAYWNzcE1TRlQAAAAASUVDIHNSR0IAAAAAAAAAAAAAAAAA
+	APbWAAEAAAAA0y1IUCAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAARY3BydAAAAVAAAAAzZGVzYwAAAYQAAABsd3RwdAAAAfAAAAAUYmtw
+	dAAAAgQAAAAUclhZWgAAAhgAAAAUZ1hZWgAAAiwAAAAUYlhZWgAAAkAAAAAUZG1uZAAA
+	AlQAAABwZG1kZAAAAsQAAACIdnVlZAAAA0wAAACGdmlldwAAA9QAAAAkbHVtaQAAA/gA
+	AAAUbWVhcwAABAwAAAAkdGVjaAAABDAAAAAMclRSQwAABDwAAAgMZ1RSQwAABDwAAAgM
+	YlRSQwAABDwAAAgMdGV4dAAAAABDb3B5cmlnaHQgKGMpIDE5OTggSGV3bGV0dC1QYWNr
+	YXJkIENvbXBhbnkAAGRlc2MAAAAAAAAAEnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAA
+	AAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAADzUQABAAAAARbMWFlaIAAAAAAAAAAA
+	AAAAAAAAAABYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFla
+	IAAAAAAAACSgAAAPhAAAts9kZXNjAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gA
+	AAAAAAAAAAAAABZJRUMgaHR0cDovL3d3dy5pZWMuY2gAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAuSUVDIDYxOTY2LTIu
+	MSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAuSUVDIDYx
+	OTY2LTIuMSBEZWZhdWx0IFJHQiBjb2xvdXIgc3BhY2UgLSBzUkdCAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAGRlc2MAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBp
+	biBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRp
+	b24gaW4gSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB2aWV3AAAA
+	AAATpP4AFF8uABDPFAAD7cwABBMLAANcngAAAAFYWVogAAAAAABMCVYAUAAAAFcf521l
+	YXMAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAKPAAAAAnNpZyAAAAAAQ1JUIGN1cnYA
+	AAAAAAAEAAAAAAUACgAPABQAGQAeACMAKAAtADIANwA7AEAARQBKAE8AVABZAF4AYwBo
+	AG0AcgB3AHwAgQCGAIsAkACVAJoAnwCkAKkArgCyALcAvADBAMYAywDQANUA2wDgAOUA
+	6wDwAPYA+wEBAQcBDQETARkBHwElASsBMgE4AT4BRQFMAVIBWQFgAWcBbgF1AXwBgwGL
+	AZIBmgGhAakBsQG5AcEByQHRAdkB4QHpAfIB+gIDAgwCFAIdAiYCLwI4AkECSwJUAl0C
+	ZwJxAnoChAKOApgCogKsArYCwQLLAtUC4ALrAvUDAAMLAxYDIQMtAzgDQwNPA1oDZgNy
+	A34DigOWA6IDrgO6A8cD0wPgA+wD+QQGBBMEIAQtBDsESARVBGMEcQR+BIwEmgSoBLYE
+	xATTBOEE8AT+BQ0FHAUrBToFSQVYBWcFdwWGBZYFpgW1BcUF1QXlBfYGBgYWBicGNwZI
+	BlkGagZ7BowGnQavBsAG0QbjBvUHBwcZBysHPQdPB2EHdAeGB5kHrAe/B9IH5Qf4CAsI
+	HwgyCEYIWghuCIIIlgiqCL4I0gjnCPsJEAklCToJTwlkCXkJjwmkCboJzwnlCfsKEQon
+	Cj0KVApqCoEKmAquCsUK3ArzCwsLIgs5C1ELaQuAC5gLsAvIC+EL+QwSDCoMQwxcDHUM
+	jgynDMAM2QzzDQ0NJg1ADVoNdA2ODakNww3eDfgOEw4uDkkOZA5/DpsOtg7SDu4PCQ8l
+	D0EPXg96D5YPsw/PD+wQCRAmEEMQYRB+EJsQuRDXEPURExExEU8RbRGMEaoRyRHoEgcS
+	JhJFEmQShBKjEsMS4xMDEyMTQxNjE4MTpBPFE+UUBhQnFEkUahSLFK0UzhTwFRIVNBVW
+	FXgVmxW9FeAWAxYmFkkWbBaPFrIW1hb6Fx0XQRdlF4kXrhfSF/cYGxhAGGUYihivGNUY
+	+hkgGUUZaxmRGbcZ3RoEGioaURp3Gp4axRrsGxQbOxtjG4obshvaHAIcKhxSHHscoxzM
+	HPUdHh1HHXAdmR3DHeweFh5AHmoelB6+HukfEx8+H2kflB+/H+ogFSBBIGwgmCDEIPAh
+	HCFIIXUhoSHOIfsiJyJVIoIiryLdIwojOCNmI5QjwiPwJB8kTSR8JKsk2iUJJTglaCWX
+	Jccl9yYnJlcmhya3JugnGCdJJ3onqyfcKA0oPyhxKKIo1CkGKTgpaymdKdAqAio1Kmgq
+	myrPKwIrNitpK50r0SwFLDksbiyiLNctDC1BLXYtqy3hLhYuTC6CLrcu7i8kL1ovkS/H
+	L/4wNTBsMKQw2zESMUoxgjG6MfIyKjJjMpsy1DMNM0YzfzO4M/E0KzRlNJ402DUTNU01
+	hzXCNf02NzZyNq426TckN2A3nDfXOBQ4UDiMOMg5BTlCOX85vDn5OjY6dDqyOu87LTtr
+	O6o76DwnPGU8pDzjPSI9YT2hPeA+ID5gPqA+4D8hP2E/oj/iQCNAZECmQOdBKUFqQaxB
+	7kIwQnJCtUL3QzpDfUPARANER0SKRM5FEkVVRZpF3kYiRmdGq0bwRzVHe0fASAVIS0iR
+	SNdJHUljSalJ8Eo3Sn1KxEsMS1NLmkviTCpMcky6TQJNSk2TTdxOJU5uTrdPAE9JT5NP
+	3VAnUHFQu1EGUVBRm1HmUjFSfFLHUxNTX1OqU/ZUQlSPVNtVKFV1VcJWD1ZcVqlW91dE
+	V5JX4FgvWH1Yy1kaWWlZuFoHWlZaplr1W0VblVvlXDVchlzWXSddeF3JXhpebF69Xw9f
+	YV+zYAVgV2CqYPxhT2GiYfViSWKcYvBjQ2OXY+tkQGSUZOllPWWSZedmPWaSZuhnPWeT
+	Z+loP2iWaOxpQ2maafFqSGqfavdrT2una/9sV2yvbQhtYG25bhJua27Ebx5veG/RcCtw
+	hnDgcTpxlXHwcktypnMBc11zuHQUdHB0zHUodYV14XY+dpt2+HdWd7N4EXhueMx5KnmJ
+	eed6RnqlewR7Y3vCfCF8gXzhfUF9oX4BfmJ+wn8jf4R/5YBHgKiBCoFrgc2CMIKSgvSD
+	V4O6hB2EgITjhUeFq4YOhnKG14c7h5+IBIhpiM6JM4mZif6KZIrKizCLlov8jGOMyo0x
+	jZiN/45mjs6PNo+ekAaQbpDWkT+RqJIRknqS45NNk7aUIJSKlPSVX5XJljSWn5cKl3WX
+	4JhMmLiZJJmQmfyaaJrVm0Kbr5wcnImc951kndKeQJ6unx2fi5/6oGmg2KFHobaiJqKW
+	owajdqPmpFakx6U4pammGqaLpv2nbqfgqFKoxKk3qamqHKqPqwKrdavprFys0K1Erbiu
+	La6hrxavi7AAsHWw6rFgsdayS7LCszizrrQltJy1E7WKtgG2ebbwt2i34LhZuNG5SrnC
+	uju6tbsuu6e8IbybvRW9j74KvoS+/796v/XAcMDswWfB48JfwtvDWMPUxFHEzsVLxcjG
+	RsbDx0HHv8g9yLzJOsm5yjjKt8s2y7bMNcy1zTXNtc42zrbPN8+40DnQutE80b7SP9LB
+	00TTxtRJ1MvVTtXR1lXW2Ndc1+DYZNjo2WzZ8dp22vvbgNwF3IrdEN2W3hzeot8p36/g
+	NuC94UThzOJT4tvjY+Pr5HPk/OWE5g3mlucf56noMui86Ubp0Opb6uXrcOv77IbtEe2c
+	7ijutO9A78zwWPDl8XLx//KM8xnzp/Q09ML1UPXe9m32+/eK+Bn4qPk4+cf6V/rn+3f8
+	B/yY/Sn9uv5L/tz/bf//0h8gISJaJGNsYXNzbmFtZVgkY2xhc3Nlc1xOU0NvbG9yU3Bh
+	Y2WiIyRcTlNDb2xvclNwYWNlWE5TT2JqZWN00h8gJidXTlNDb2xvcqImJAAIABEAGgAk
+	ACkAMgA3AEkATABRAFMAWgBgAGsAeAB+AIsAoACnANMA/gEAAQIBBAELARABFgEYARoB
+	HA1oDW0NeA2BDY4NkQ2eDacNrA20AAAAAAAAAgEAAAAAAAAAKAAAAAAAAAAAAAAAAAAA
+	Dbc=
+	</data>
+	<key>ShowActiveProcessInTabTitle</key>
+	<false/>
+	<key>ShowActiveProcessInTitle</key>
+	<false/>
+	<key>ShowActivityIndicatorInTab</key>
+	<false/>
+	<key>ShowCommandKeyInTitle</key>
+	<false/>
+	<key>ShowComponentsWhenTabHasCustomTitle</key>
+	<true/>
+	<key>ShowDimensionsInTitle</key>
+	<false/>
+	<key>ShowRepresentedURLInTabTitle</key>
+	<false/>
+	<key>ShowRepresentedURLInTitle</key>
+	<false/>
+	<key>ShowRepresentedURLPathInTitle</key>
+	<false/>
+	<key>ShowShellCommandInTitle</key>
+	<false/>
+	<key>ShowTTYNameInTitle</key>
+	<false/>
+	<key>ShowWindowSettingsNameInTitle</key>
+	<false/>
+	<key>TerminalType</key>
+	<string>xterm</string>
+	<key>TextBoldColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECgwLjgwMTk4NTU2MTggMC43MzU3NzAwNDY3IDAuNTU1MDUz
+	NTMyMSAxTxAnMC43NTY0MTcxNTUzIDAuNjg1MjI5MjQxOCAwLjQ4MjY3MjM5MzMAEAGA
+	AoAF0xgZERobHFROU0lEVU5TSUNDEAeAA4AETxEMSAAADEhMaW5vAhAAAG1udHJSR0Ig
+	WFlaIAfOAAIACQAGADEAAGFjc3BNU0ZUAAAAAElFQyBzUkdCAAAAAAAAAAAAAAAAAAD2
+	1gABAAAAANMtSFAgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAEWNwcnQAAAFQAAAAM2Rlc2MAAAGEAAAAbHd0cHQAAAHwAAAAFGJrcHQA
+	AAIEAAAAFHJYWVoAAAIYAAAAFGdYWVoAAAIsAAAAFGJYWVoAAAJAAAAAFGRtbmQAAAJU
+	AAAAcGRtZGQAAALEAAAAiHZ1ZWQAAANMAAAAhnZpZXcAAAPUAAAAJGx1bWkAAAP4AAAA
+	FG1lYXMAAAQMAAAAJHRlY2gAAAQwAAAADHJUUkMAAAQ8AAAIDGdUUkMAAAQ8AAAIDGJU
+	UkMAAAQ8AAAIDHRleHQAAAAAQ29weXJpZ2h0IChjKSAxOTk4IEhld2xldHQtUGFja2Fy
+	ZCBDb21wYW55AABkZXNjAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAA
+	EnNSR0IgSUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAABYWVogAAAAAAAA81EAAQAAAAEWzFhZWiAAAAAAAAAAAAAA
+	AAAAAAAAWFlaIAAAAAAAAG+iAAA49QAAA5BYWVogAAAAAAAAYpkAALeFAAAY2lhZWiAA
+	AAAAAAAkoAAAD4QAALbPZGVzYwAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAA
+	AAAAAAAAAAAWSUVDIGh0dHA6Ly93d3cuaWVjLmNoAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlc2MAAAAAAAAALklFQyA2MTk2Ni0yLjEg
+	RGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAALklFQyA2MTk2
+	Ni0yLjEgRGVmYXVsdCBSR0IgY29sb3VyIHNwYWNlIC0gc1JHQgAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAABkZXNjAAAAAAAAACxSZWZlcmVuY2UgVmlld2luZyBDb25kaXRpb24gaW4g
+	SUVDNjE5NjYtMi4xAAAAAAAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9u
+	IGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdmlldwAAAAAA
+	E6T+ABRfLgAQzxQAA+3MAAQTCwADXJ4AAAABWFlaIAAAAAAATAlWAFAAAABXH+dtZWFz
+	AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAACjwAAAAJzaWcgAAAAAENSVCBjdXJ2AAAA
+	AAAABAAAAAAFAAoADwAUABkAHgAjACgALQAyADcAOwBAAEUASgBPAFQAWQBeAGMAaABt
+	AHIAdwB8AIEAhgCLAJAAlQCaAJ8ApACpAK4AsgC3ALwAwQDGAMsA0ADVANsA4ADlAOsA
+	8AD2APsBAQEHAQ0BEwEZAR8BJQErATIBOAE+AUUBTAFSAVkBYAFnAW4BdQF8AYMBiwGS
+	AZoBoQGpAbEBuQHBAckB0QHZAeEB6QHyAfoCAwIMAhQCHQImAi8COAJBAksCVAJdAmcC
+	cQJ6AoQCjgKYAqICrAK2AsECywLVAuAC6wL1AwADCwMWAyEDLQM4A0MDTwNaA2YDcgN+
+	A4oDlgOiA64DugPHA9MD4APsA/kEBgQTBCAELQQ7BEgEVQRjBHEEfgSMBJoEqAS2BMQE
+	0wThBPAE/gUNBRwFKwU6BUkFWAVnBXcFhgWWBaYFtQXFBdUF5QX2BgYGFgYnBjcGSAZZ
+	BmoGewaMBp0GrwbABtEG4wb1BwcHGQcrBz0HTwdhB3QHhgeZB6wHvwfSB+UH+AgLCB8I
+	MghGCFoIbgiCCJYIqgi+CNII5wj7CRAJJQk6CU8JZAl5CY8JpAm6Cc8J5Qn7ChEKJwo9
+	ClQKagqBCpgKrgrFCtwK8wsLCyILOQtRC2kLgAuYC7ALyAvhC/kMEgwqDEMMXAx1DI4M
+	pwzADNkM8w0NDSYNQA1aDXQNjg2pDcMN3g34DhMOLg5JDmQOfw6bDrYO0g7uDwkPJQ9B
+	D14Peg+WD7MPzw/sEAkQJhBDEGEQfhCbELkQ1xD1ERMRMRFPEW0RjBGqEckR6BIHEiYS
+	RRJkEoQSoxLDEuMTAxMjE0MTYxODE6QTxRPlFAYUJxRJFGoUixStFM4U8BUSFTQVVhV4
+	FZsVvRXgFgMWJhZJFmwWjxayFtYW+hcdF0EXZReJF64X0hf3GBsYQBhlGIoYrxjVGPoZ
+	IBlFGWsZkRm3Gd0aBBoqGlEadxqeGsUa7BsUGzsbYxuKG7Ib2hwCHCocUhx7HKMczBz1
+	HR4dRx1wHZkdwx3sHhYeQB5qHpQevh7pHxMfPh9pH5Qfvx/qIBUgQSBsIJggxCDwIRwh
+	SCF1IaEhziH7IiciVSKCIq8i3SMKIzgjZiOUI8Ij8CQfJE0kfCSrJNolCSU4JWgllyXH
+	JfcmJyZXJocmtyboJxgnSSd6J6sn3CgNKD8ocSiiKNQpBik4KWspnSnQKgIqNSpoKpsq
+	zysCKzYraSudK9EsBSw5LG4soizXLQwtQS12Last4S4WLkwugi63Lu4vJC9aL5Evxy/+
+	MDUwbDCkMNsxEjFKMYIxujHyMioyYzKbMtQzDTNGM38zuDPxNCs0ZTSeNNg1EzVNNYc1
+	wjX9Njc2cjauNuk3JDdgN5w31zgUOFA4jDjIOQU5Qjl/Obw5+To2OnQ6sjrvOy07azuq
+	O+g8JzxlPKQ84z0iPWE9oT3gPiA+YD6gPuA/IT9hP6I/4kAjQGRApkDnQSlBakGsQe5C
+	MEJyQrVC90M6Q31DwEQDREdEikTORRJFVUWaRd5GIkZnRqtG8Ec1R3tHwEgFSEtIkUjX
+	SR1JY0mpSfBKN0p9SsRLDEtTS5pL4kwqTHJMuk0CTUpNk03cTiVObk63TwBPSU+TT91Q
+	J1BxULtRBlFQUZtR5lIxUnxSx1MTU19TqlP2VEJUj1TbVShVdVXCVg9WXFapVvdXRFeS
+	V+BYL1h9WMtZGllpWbhaB1pWWqZa9VtFW5Vb5Vw1XIZc1l0nXXhdyV4aXmxevV8PX2Ff
+	s2AFYFdgqmD8YU9homH1YklinGLwY0Njl2PrZEBklGTpZT1lkmXnZj1mkmboZz1nk2fp
+	aD9olmjsaUNpmmnxakhqn2r3a09rp2v/bFdsr20IbWBtuW4SbmtuxG8eb3hv0XArcIZw
+	4HE6cZVx8HJLcqZzAXNdc7h0FHRwdMx1KHWFdeF2Pnabdvh3VnezeBF4bnjMeSp5iXnn
+	ekZ6pXsEe2N7wnwhfIF84X1BfaF+AX5ifsJ/I3+Ef+WAR4CogQqBa4HNgjCCkoL0g1eD
+	uoQdhICE44VHhauGDoZyhteHO4efiASIaYjOiTOJmYn+imSKyoswi5aL/IxjjMqNMY2Y
+	jf+OZo7OjzaPnpAGkG6Q1pE/kaiSEZJ6kuOTTZO2lCCUipT0lV+VyZY0lp+XCpd1l+CY
+	TJi4mSSZkJn8mmia1ZtCm6+cHJyJnPedZJ3SnkCerp8dn4uf+qBpoNihR6G2oiailqMG
+	o3aj5qRWpMelOKWpphqmi6b9p26n4KhSqMSpN6mpqhyqj6sCq3Wr6axcrNCtRK24ri2u
+	oa8Wr4uwALB1sOqxYLHWskuywrM4s660JbSctRO1irYBtnm28Ldot+C4WbjRuUq5wro7
+	urW7LrunvCG8m70VvY++Cr6Evv+/er/1wHDA7MFnwePCX8Lbw1jD1MRRxM7FS8XIxkbG
+	w8dBx7/IPci8yTrJuco4yrfLNsu2zDXMtc01zbXONs62zzfPuNA50LrRPNG+0j/SwdNE
+	08bUSdTL1U7V0dZV1tjXXNfg2GTY6Nls2fHadtr724DcBdyK3RDdlt4c3qLfKd+v4Dbg
+	veFE4cziU+Lb42Pj6+Rz5PzlhOYN5pbnH+ep6DLovOlG6dDqW+rl63Dr++yG7RHtnO4o
+	7rTvQO/M8Fjw5fFy8f/yjPMZ86f0NPTC9VD13vZt9vv3ivgZ+Kj5OPnH+lf65/t3/Af8
+	mP0p/br+S/7c/23//9IfICEiWiRjbGFzc25hbWVYJGNsYXNzZXNcTlNDb2xvclNwYWNl
+	oiMkXE5TQ29sb3JTcGFjZVhOU09iamVjdNIfICYnV05TQ29sb3KiJiQACAARABoAJAAp
+	ADIANwBJAEwAUQBTAFoAYABrAHgAfgCLAKAApwDSAPwA/gEAAQIBCQEOARQBFgEYARoN
+	Zg1rDXYNfw2MDY8NnA2lDaoNsgAAAAAAAAIBAAAAAAAAACgAAAAAAAAAAAAAAAAAAA21
+	</data>
+	<key>TextColor</key>
+	<data>
+	YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMS
+	AAGGoF8QD05TS2V5ZWRBcmNoaXZlctEICVRyb290gAGmCwwXHR4lVSRudWxs1Q0ODxAR
+	EhMUFRZcTlNDb21wb25lbnRzVU5TUkdCXE5TQ29sb3JTcGFjZV8QEk5TQ3VzdG9tQ29s
+	b3JTcGFjZVYkY2xhc3NPECYwLjcxOTQwMjEzNDQgMC42NjA5ODgxNTIgMC41MDEzMjYy
+	NjMgMU8QJzAuNjYwODU1MjkzMyAwLjYwMDE1MjY3MTMgMC40MjY4MTE1NzU5ABABgAKA
+	BdMYGREaGxxUTlNJRFVOU0lDQxAHgAOABE8RDEgAAAxITGlubwIQAABtbnRyUkdCIFhZ
+	WiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYA
+	AQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAAC
+	BAAAABRyWFlaAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAACVAAA
+	AHBkbWRkAAACxAAAAIh2dWVkAAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD+AAAABRt
+	ZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJDAAAEPAAACAxnVFJDAAAEPAAACAxiVFJD
+	AAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBhY2thcmQg
+	Q29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAABJz
+	UkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAAAAAA
+	AAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAA
+	AAAAJKAAAA+EAAC2z2Rlc2MAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAA
+	AAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERl
+	ZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5NjYt
+	Mi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAAAAAAAAAA
+	AAAAAAAAZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGluIElF
+	QzYxOTY2LTIuMQAAAAAAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBp
+	biBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZpZXcAAAAAABOk
+	/gAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAAVx/nbWVhcwAA
+	AAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAAAAAA
+	AAQAAAAABQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgAbQBy
+	AHcAfACBAIYAiwCQAJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDrAPAA
+	9gD7AQEBBwENARMBGQEfASUBKwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsBkgGa
+	AaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJnAnEC
+	egKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMhAy0DOANDA08DWgNmA3IDfgOK
+	A5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH4EjASaBKgEtgTEBNME
+	4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYGJwY3BkgGWQZq
+	BnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICwgfCDII
+	RghaCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicKPQpU
+	CmoKgQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyODKcM
+	wAzZDPMNDQ0mDUANWg10DY4NqQ3DDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUPQQ9e
+	D3oPlg+zD88P7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxImEkUS
+	ZBKEEqMSwxLjEwMTIxNDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYVeBWb
+	Fb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6GSAZ
+	RRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc9R0e
+	HUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4faR+UH78f6iAVIEEgbCCYIMQg8CEcIUgh
+	dSGhIc4h+yInIlUigiKvIt0jCiM4I2YjlCPCI/AkHyRNJHwkqyTaJQklOCVoJZclxyX3
+	JicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYpOClrKZ0p0CoCKjUqaCqbKs8r
+	Ais2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQvWi+RL8cv/jA1
+	MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1TTWHNcI1
+	/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7qjvo
+	PCc8ZTykPOM9Ij1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHuQjBC
+	ckK1QvdDOkN9Q8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI10kd
+	SWNJqUnwSjdKfUrESwxLU0uaS+JMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0/dUCdQ
+	cVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVVwlYPVlxWqVb3V0RXklfg
+	WC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5sXr1fD19hX7Ng
+	BWBXYKpg/GFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn6Wg/
+	aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CGcOBx
+	OnGVcfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl553pG
+	eqV7BHtje8J8IXyBfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INXg7qE
+	HYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ/opkisqLMIuWi/yMY4zKjTGNmI3/
+	jmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmWNJaflwqXdZfgmEyY
+	uJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDYoUehtqImopajBqN2
+	o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+rAqt1q+msXKzQrUStuK4trqGv
+	Fq+LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6O7q1
+	uy67p7whvJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvFyMZGxsPH
+	Qce/yD3IvMk6ybnKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHTRNPG
+	1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A24L3h
+	ROHM4lPi2+Nj4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ6lvq5etw6/vshu0R7ZzuKO60
+	70DvzPBY8OXxcvH/8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH/Jj9
+	Kf26/kv+3P9t///SHyAhIlokY2xhc3NuYW1lWCRjbGFzc2VzXE5TQ29sb3JTcGFjZaIj
+	JFxOU0NvbG9yU3BhY2VYTlNPYmplY3TSHyAmJ1dOU0NvbG9yoiYkAAgAEQAaACQAKQAy
+	ADcASQBMAFEAUwBaAGAAawB4AH4AiwCgAKcA0AD6APwA/gEAAQcBDAESARQBFgEYDWQN
+	aQ10DX0Nig2NDZoNow2oDbAAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAANsw==
+	</data>
+	<key>UseBoldFonts</key>
+	<false/>
+	<key>UseBrightBold</key>
+	<true/>
+	<key>VisualBell</key>
+	<false/>
+	<key>VisualBellOnlyWhenMuted</key>
+	<false/>
+	<key>WindowTitle</key>
+	<string>Terminal</string>
+	<key>name</key>
+	<string>Dark</string>
+	<key>noWarnProcesses</key>
+	<array>
+		<dict>
+			<key>ProcessName</key>
+			<string>screen</string>
+		</dict>
+		<dict>
+			<key>ProcessName</key>
+			<string>tmux</string>
+		</dict>
+		<dict>
+			<key>ProcessName</key>
+			<string>atch</string>
+		</dict>
+	</array>
+	<key>rowCount</key>
+	<integer>25</integer>
+	<key>shellExitAction</key>
+	<integer>1</integer>
+	<key>type</key>
+	<string>Window Settings</string>
+	<key>useOptionAsMetaKey</key>
+	<false/>
+</dict>
+</plist>
diff --git a/etc/Go-Mono-Bold-Italic.ttf b/etc/Go-Mono-Bold-Italic.ttf
new file mode 100644
index 00000000..c138a9e1
--- /dev/null
+++ b/etc/Go-Mono-Bold-Italic.ttf
Binary files differdiff --git a/etc/Go-Mono-Bold.ttf b/etc/Go-Mono-Bold.ttf
new file mode 100644
index 00000000..551da07f
--- /dev/null
+++ b/etc/Go-Mono-Bold.ttf
Binary files differdiff --git a/etc/Go-Mono-Italic.ttf b/etc/Go-Mono-Italic.ttf
new file mode 100644
index 00000000..22d4390e
--- /dev/null
+++ b/etc/Go-Mono-Italic.ttf
Binary files differdiff --git a/etc/Go-Mono.ttf b/etc/Go-Mono.ttf
new file mode 100644
index 00000000..71e30123
--- /dev/null
+++ b/etc/Go-Mono.ttf
Binary files differdiff --git a/etc/README.Go-Mono b/etc/README.Go-Mono
new file mode 100644
index 00000000..7043c362
--- /dev/null
+++ b/etc/README.Go-Mono
@@ -0,0 +1,36 @@
+These fonts were created by the Bigelow & Holmes foundry specifically for the
+Go project. See https://blog.golang.org/go-fonts for details.
+
+They are licensed under the same open source license as the rest of the Go
+project's software:
+
+Copyright (c) 2016 Bigelow & Holmes Inc.. All rights reserved.
+
+Distribution of this font is governed by the following license. If you do not
+agree to this license, including the disclaimer, do not distribute or modify
+this font.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice,
+	  this list of conditions and the following disclaimer.
+
+	* 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.
+
+	* Neither the name of Google Inc. nor the names of its contributors may be
+	  used to endorse or promote products derived from this software without
+	  specific prior written permission.
+
+DISCLAIMER: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
diff --git a/etc/code.map b/etc/code.map
new file mode 100644
index 00000000..a3749b8d
--- /dev/null
+++ b/etc/code.map
@@ -0,0 +1,20 @@
+include "/usr/share/kbd/keymaps/i386/qwerty/us.map.gz"
+
+keycode 2 = exclam one
+keycode 3 = at two
+keycode 4 = numbersign three
+keycode 5 = dollar four
+keycode 6 = percent five
+keycode 7 = asciicircum six
+keycode 8 = ampersand seven
+keycode 9 = asterisk eight
+keycode 10 = parenleft nine
+keycode 11 = parenright zero
+keycode 12 = underscore minus
+keycode 26 = braceleft bracketleft
+keycode 27 = braceright bracketright
+keycode 43 = bar backslash
+keycode 58 = Escape
+
+keycode 100 = Compose
+keycode 125 = Escape
diff --git a/etc/psf/.gitignore b/etc/psf/.gitignore
new file mode 100644
index 00000000..446e6b46
--- /dev/null
+++ b/etc/psf/.gitignore
@@ -0,0 +1,2 @@
+*.png
+*.psfu
diff --git a/etc/psf/Makefile b/etc/psf/Makefile
new file mode 100644
index 00000000..e92178cd
--- /dev/null
+++ b/etc/psf/Makefile
@@ -0,0 +1,24 @@
+TABLE = default.u
+
+FONTS += sans6x8.psfu
+FONTS += sans6x10.psfu
+FONTS += sans6x12.psfu
+
+PNGS = $(FONTS:psfu=png)
+
+all: $(FONTS)
+
+png: $(PNGS)
+
+$(FONTS): $(TABLE)
+
+.SUFFIXES: .psf .psfu .png
+
+.psf.psfu:
+	psfaddtable $< $(TABLE) $@
+
+.psf.png:
+	psf2png $< > $@
+
+clean:
+	rm -f $(FONTS) $(PNGS)
diff --git a/etc/psf/default.u b/etc/psf/default.u
new file mode 100644
index 00000000..790ad92b
--- /dev/null
+++ b/etc/psf/default.u
@@ -0,0 +1,259 @@
+#
+# Character table extracted from font default8x16.psfu
+#
+0x000	U+2008
+0x001	U+263a
+0x002	U+263b
+0x003	U+2665
+0x004	U+2666
+0x005	U+2663
+0x006	U+2660
+0x007	U+2022
+0x008	U+25d8
+0x009	U+25cb
+0x00a	U+25d9
+0x00b	U+2642
+0x00c	U+2640
+0x00d	U+266a
+0x00e	U+266b U+266c
+0x00f	U+263c
+0x010	U+25b6 U+25ba
+0x011	U+25c0 U+25c4
+0x012	U+2195
+0x013	U+203c
+0x014	U+00b6
+0x015	U+00a7
+0x016	U+25ac
+0x017	U+21a8
+0x018	U+2191
+0x019	U+2193
+0x01a	U+2192
+0x01b	U+2190
+0x01c	U+221f U+2319
+0x01d	U+2194
+0x01e	U+25b2
+0x01f	U+25bc
+0x020	U+0020 U+00a0 U+2000 U+2001 U+2002 U+2003 U+2004 U+2005 U+2006 U+2007 U+2008 U+2009 U+200a U+202f
+0x021	U+0021
+0x022	U+0022
+0x023	U+0023
+0x024	U+0024
+0x025	U+0025
+0x026	U+0026
+0x027	U+0027
+0x028	U+0028
+0x029	U+0029
+0x02a	U+002a
+0x02b	U+002b
+0x02c	U+002c
+0x02d	U+002d
+0x02e	U+002e
+0x02f	U+002f
+0x030	U+0030
+0x031	U+0031
+0x032	U+0032
+0x033	U+0033
+0x034	U+0034
+0x035	U+0035
+0x036	U+0036
+0x037	U+0037
+0x038	U+0038
+0x039	U+0039
+0x03a	U+003a
+0x03b	U+003b
+0x03c	U+003c
+0x03d	U+003d
+0x03e	U+003e
+0x03f	U+003f
+0x040	U+0040
+0x041	U+0041
+0x042	U+0042
+0x043	U+0043
+0x044	U+0044
+0x045	U+0045
+0x046	U+0046
+0x047	U+0047
+0x048	U+0048
+0x049	U+0049
+0x04a	U+004a
+0x04b	U+004b
+0x04c	U+004c
+0x04d	U+004d
+0x04e	U+004e
+0x04f	U+004f
+0x050	U+0050
+0x051	U+0051
+0x052	U+0052
+0x053	U+0053
+0x054	U+0054
+0x055	U+0055
+0x056	U+0056
+0x057	U+0057
+0x058	U+0058
+0x059	U+0059
+0x05a	U+005a
+0x05b	U+005b
+0x05c	U+005c
+0x05d	U+005d
+0x05e	U+005e
+0x05f	U+005f
+0x060	U+0060
+0x061	U+0061
+0x062	U+0062
+0x063	U+0063
+0x064	U+0064
+0x065	U+0065
+0x066	U+0066
+0x067	U+0067
+0x068	U+0068
+0x069	U+0069
+0x06a	U+006a
+0x06b	U+006b
+0x06c	U+006c
+0x06d	U+006d
+0x06e	U+006e
+0x06f	U+006f
+0x070	U+0070
+0x071	U+0071
+0x072	U+0072
+0x073	U+0073
+0x074	U+0074
+0x075	U+0075
+0x076	U+0076
+0x077	U+0077
+0x078	U+0078
+0x079	U+0079
+0x07a	U+007a
+0x07b	U+007b
+0x07c	U+007c
+0x07d	U+007d
+0x07e	U+007e
+0x07f	U+2302
+0x080	U+00c7
+0x081	U+00fc
+0x082	U+00e9
+0x083	U+00e2
+0x084	U+00e4
+0x085	U+00e0
+0x086	U+00e5
+0x087	U+00e7
+0x088	U+00ea
+0x089	U+00eb
+0x08a	U+00e8
+0x08b	U+00ef
+0x08c	U+00ee
+0x08d	U+00ec
+0x08e	U+00c4
+0x08f	U+00c5 U+212b
+0x090	U+00c9
+0x091	U+00e6
+0x092	U+00c6
+0x093	U+00f4
+0x094	U+00f6
+0x095	U+00f2
+0x096	U+00fb
+0x097	U+00f9
+0x098	U+00ff
+0x099	U+00d6
+0x09a	U+00dc
+0x09b	U+00a2
+0x09c	U+00a3
+0x09d	U+00a5
+0x09e	U+20a7
+0x09f	U+0192
+0x0a0	U+00e1
+0x0a1	U+00ed
+0x0a2	U+00f3
+0x0a3	U+00fa
+0x0a4	U+00f1
+0x0a5	U+00d1
+0x0a6	U+00aa
+0x0a7	U+00ba
+0x0a8	U+00bf
+0x0a9	U+2310
+0x0aa	U+00ac
+0x0ab	U+00bd
+0x0ac	U+00bc
+0x0ad	U+00a1
+0x0ae	U+00ab
+0x0af	U+00bb
+0x0b0	U+2591
+0x0b1	U+2592
+0x0b2	U+2593
+0x0b3	U+2502
+0x0b4	U+2524
+0x0b5	U+2561
+0x0b6	U+2562
+0x0b7	U+2556
+0x0b8	U+2555
+0x0b9	U+2563
+0x0ba	U+2551
+0x0bb	U+2557
+0x0bc	U+255d
+0x0bd	U+255c
+0x0be	U+255b
+0x0bf	U+2510
+0x0c0	U+2514
+0x0c1	U+2534
+0x0c2	U+252c
+0x0c3	U+251c
+0x0c4	U+2500
+0x0c5	U+253c
+0x0c6	U+255e
+0x0c7	U+255f
+0x0c8	U+255a
+0x0c9	U+2554
+0x0ca	U+2569
+0x0cb	U+2566
+0x0cc	U+2560
+0x0cd	U+2550
+0x0ce	U+256c
+0x0cf	U+2567
+0x0d0	U+2568
+0x0d1	U+2564
+0x0d2	U+2565
+0x0d3	U+2559
+0x0d4	U+2558
+0x0d5	U+2552
+0x0d6	U+2553
+0x0d7	U+256b
+0x0d8	U+256a
+0x0d9	U+2518
+0x0da	U+250c
+0x0db	U+2588
+0x0dc	U+2584
+0x0dd	U+258c
+0x0de	U+2590
+0x0df	U+2580
+0x0e0	U+03b1
+0x0e1	U+00df U+03b2
+0x0e2	U+0393
+0x0e3	U+03c0
+0x0e4	U+03a3
+0x0e5	U+03c3
+0x0e6	U+00b5 U+03bc
+0x0e7	U+03c4
+0x0e8	U+03a6
+0x0e9	U+0398
+0x0ea	U+03a9 U+2126
+0x0eb	U+03b4
+0x0ec	U+221e
+0x0ed	U+03c6 U+2205 U+2300
+0x0ee	U+03b5 U+2208
+0x0ef	U+2229
+0x0f0	U+2261
+0x0f1	U+00b1
+0x0f2	U+2265
+0x0f3	U+2264
+0x0f4	U+2320
+0x0f5	U+2321
+0x0f6	U+00f7
+0x0f7	U+2248
+0x0f8	U+00b0
+0x0f9	U+2219 U+22c5
+0x0fa	U+00b7
+0x0fb	U+221a
+0x0fc	U+207f
+0x0fd	U+00b2
+0x0fe	U+220e U+25a0
+0x0ff	U+00a0
diff --git a/etc/psf/sans6x10.psf b/etc/psf/sans6x10.psf
new file mode 100644
index 00000000..09bb1af6
--- /dev/null
+++ b/etc/psf/sans6x10.psf
Binary files differdiff --git a/etc/psf/sans6x12.psf b/etc/psf/sans6x12.psf
new file mode 100644
index 00000000..75c1fd49
--- /dev/null
+++ b/etc/psf/sans6x12.psf
Binary files differdiff --git a/etc/psf/sans6x8.psf b/etc/psf/sans6x8.psf
new file mode 100644
index 00000000..fef671d8
--- /dev/null
+++ b/etc/psf/sans6x8.psf
Binary files differdiff --git a/etc/wsconsctl.conf b/etc/wsconsctl.conf
new file mode 100644
index 00000000..05f29b6a
--- /dev/null
+++ b/etc/wsconsctl.conf
@@ -0,0 +1,26 @@
+display.brightness=50%
+keyboard.backlight=0%
+
+mouse1.tp.tapping=1
+mouse1.tp.scaling=0.2
+mouse1.reverse_scrolling=1
+
+keyboard1.repeat.del1=200
+keyboard1.repeat.deln=50
+
+keyboard1.map+='keycode 30 = exclam 1'
+keyboard1.map+='keycode 31 = at 2'
+keyboard1.map+='keycode 32 = numbersign 3'
+keyboard1.map+='keycode 33 = dollar 4'
+keyboard1.map+='keycode 34 = percent 5'
+keyboard1.map+='keycode 35 = asciicircum 6'
+keyboard1.map+='keycode 36 = ampersand 7'
+keyboard1.map+='keycode 37 = asterisk 8'
+keyboard1.map+='keycode 38 = parenleft 9'
+keyboard1.map+='keycode 39 = parenright 0'
+keyboard1.map+='keycode 45 = underscore minus'
+keyboard1.map+='keycode 47 = braceleft bracketleft'
+keyboard1.map+='keycode 48 = braceright bracketright'
+keyboard1.map+='keycode 49 = bar backslash'
+keyboard1.map+='keycode 50 = bar backslash'
+keyboard1.map+='keycode 57 = Escape'
diff --git a/filter.c b/filter.c
deleted file mode 100644
index 70f5b749..00000000
--- a/filter.c
+++ /dev/null
@@ -1,457 +0,0 @@
-/* filter.c: filter framework functions
- *
- * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
- *
- * Licensed under GNU General Public License v2
- *   (see COPYING for full license text)
- */
-
-#include "cgit.h"
-#include "html.h"
-#ifndef NO_LUA
-#include <dlfcn.h>
-#include <lua.h>
-#include <lualib.h>
-#include <lauxlib.h>
-#endif
-
-static inline void reap_filter(struct cgit_filter *filter)
-{
-	if (filter && filter->cleanup)
-		filter->cleanup(filter);
-}
-
-void cgit_cleanup_filters(void)
-{
-	int i;
-	reap_filter(ctx.cfg.about_filter);
-	reap_filter(ctx.cfg.commit_filter);
-	reap_filter(ctx.cfg.source_filter);
-	reap_filter(ctx.cfg.email_filter);
-	reap_filter(ctx.cfg.owner_filter);
-	reap_filter(ctx.cfg.auth_filter);
-	for (i = 0; i < cgit_repolist.count; ++i) {
-		reap_filter(cgit_repolist.repos[i].about_filter);
-		reap_filter(cgit_repolist.repos[i].commit_filter);
-		reap_filter(cgit_repolist.repos[i].source_filter);
-		reap_filter(cgit_repolist.repos[i].email_filter);
-		reap_filter(cgit_repolist.repos[i].owner_filter);
-	}
-}
-
-static int open_exec_filter(struct cgit_filter *base, va_list ap)
-{
-	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
-	int pipe_fh[2];
-	int i;
-
-	for (i = 0; i < filter->base.argument_count; i++)
-		filter->argv[i + 1] = va_arg(ap, char *);
-
-	filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
-		"Unable to duplicate STDOUT");
-	chk_zero(pipe(pipe_fh), "Unable to create pipe to subprocess");
-	filter->pid = chk_non_negative(fork(), "Unable to create subprocess");
-	if (filter->pid == 0) {
-		close(pipe_fh[1]);
-		chk_non_negative(dup2(pipe_fh[0], STDIN_FILENO),
-			"Unable to use pipe as STDIN");
-		execvp(filter->cmd, filter->argv);
-		die_errno("Unable to exec subprocess %s", filter->cmd);
-	}
-	close(pipe_fh[0]);
-	chk_non_negative(dup2(pipe_fh[1], STDOUT_FILENO),
-		"Unable to use pipe as STDOUT");
-	close(pipe_fh[1]);
-	return 0;
-}
-
-static int close_exec_filter(struct cgit_filter *base)
-{
-	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
-	int i, exit_status = 0;
-
-	chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
-		"Unable to restore STDOUT");
-	close(filter->old_stdout);
-	if (filter->pid < 0)
-		goto done;
-	waitpid(filter->pid, &exit_status, 0);
-	if (WIFEXITED(exit_status))
-		goto done;
-	die("Subprocess %s exited abnormally", filter->cmd);
-
-done:
-	for (i = 0; i < filter->base.argument_count; i++)
-		filter->argv[i + 1] = NULL;
-	return WEXITSTATUS(exit_status);
-
-}
-
-static void fprintf_exec_filter(struct cgit_filter *base, FILE *f, const char *prefix)
-{
-	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
-	fprintf(f, "%sexec:%s\n", prefix, filter->cmd);
-}
-
-static void cleanup_exec_filter(struct cgit_filter *base)
-{
-	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
-	if (filter->argv) {
-		free(filter->argv);
-		filter->argv = NULL;
-	}
-	if (filter->cmd) {
-		free(filter->cmd);
-		filter->cmd = NULL;
-	}
-}
-
-static struct cgit_filter *new_exec_filter(const char *cmd, int argument_count)
-{
-	struct cgit_exec_filter *f;
-	int args_size = 0;
-
-	f = xmalloc(sizeof(*f));
-	/* We leave argv for now and assign it below. */
-	cgit_exec_filter_init(f, xstrdup(cmd), NULL);
-	f->base.argument_count = argument_count;
-	args_size = (2 + argument_count) * sizeof(char *);
-	f->argv = xmalloc(args_size);
-	memset(f->argv, 0, args_size);
-	f->argv[0] = f->cmd;
-	return &f->base;
-}
-
-void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv)
-{
-	memset(filter, 0, sizeof(*filter));
-	filter->base.open = open_exec_filter;
-	filter->base.close = close_exec_filter;
-	filter->base.fprintf = fprintf_exec_filter;
-	filter->base.cleanup = cleanup_exec_filter;
-	filter->cmd = cmd;
-	filter->argv = argv;
-	/* The argument count for open_filter is zero by default, unless called from new_filter, above. */
-	filter->base.argument_count = 0;
-}
-
-#ifdef NO_LUA
-void cgit_init_filters(void)
-{
-}
-#endif
-
-#ifndef NO_LUA
-static ssize_t (*libc_write)(int fd, const void *buf, size_t count);
-static ssize_t (*filter_write)(struct cgit_filter *base, const void *buf, size_t count) = NULL;
-static struct cgit_filter *current_write_filter = NULL;
-
-void cgit_init_filters(void)
-{
-	libc_write = dlsym(RTLD_NEXT, "write");
-	if (!libc_write)
-		die("Could not locate libc's write function");
-}
-
-ssize_t write(int fd, const void *buf, size_t count)
-{
-	if (fd != STDOUT_FILENO || !filter_write)
-		return libc_write(fd, buf, count);
-	return filter_write(current_write_filter, buf, count);
-}
-
-static inline void hook_write(struct cgit_filter *filter, ssize_t (*new_write)(struct cgit_filter *base, const void *buf, size_t count))
-{
-	/* We want to avoid buggy nested patterns. */
-	assert(filter_write == NULL);
-	assert(current_write_filter == NULL);
-	current_write_filter = filter;
-	filter_write = new_write;
-}
-
-static inline void unhook_write(void)
-{
-	assert(filter_write != NULL);
-	assert(current_write_filter != NULL);
-	filter_write = NULL;
-	current_write_filter = NULL;
-}
-
-struct lua_filter {
-	struct cgit_filter base;
-	char *script_file;
-	lua_State *lua_state;
-};
-
-static void error_lua_filter(struct lua_filter *filter)
-{
-	die("Lua error in %s: %s", filter->script_file, lua_tostring(filter->lua_state, -1));
-	lua_pop(filter->lua_state, 1);
-}
-
-static ssize_t write_lua_filter(struct cgit_filter *base, const void *buf, size_t count)
-{
-	struct lua_filter *filter = (struct lua_filter *)base;
-
-	lua_getglobal(filter->lua_state, "filter_write");
-	lua_pushlstring(filter->lua_state, buf, count);
-	if (lua_pcall(filter->lua_state, 1, 0, 0)) {
-		error_lua_filter(filter);
-		errno = EIO;
-		return -1;
-	}
-	return count;
-}
-
-static inline int hook_lua_filter(lua_State *lua_state, void (*fn)(const char *txt))
-{
-	const char *str;
-	ssize_t (*save_filter_write)(struct cgit_filter *base, const void *buf, size_t count);
-	struct cgit_filter *save_filter;
-
-	str = lua_tostring(lua_state, 1);
-	if (!str)
-		return 0;
-
-	save_filter_write = filter_write;
-	save_filter = current_write_filter;
-	unhook_write();
-	fn(str);
-	hook_write(save_filter, save_filter_write);
-
-	return 0;
-}
-
-static int html_lua_filter(lua_State *lua_state)
-{
-	return hook_lua_filter(lua_state, html);
-}
-
-static int html_txt_lua_filter(lua_State *lua_state)
-{
-	return hook_lua_filter(lua_state, html_txt);
-}
-
-static int html_attr_lua_filter(lua_State *lua_state)
-{
-	return hook_lua_filter(lua_state, html_attr);
-}
-
-static int html_url_path_lua_filter(lua_State *lua_state)
-{
-	return hook_lua_filter(lua_state, html_url_path);
-}
-
-static int html_url_arg_lua_filter(lua_State *lua_state)
-{
-	return hook_lua_filter(lua_state, html_url_arg);
-}
-
-static int html_include_lua_filter(lua_State *lua_state)
-{
-	return hook_lua_filter(lua_state, (void (*)(const char *))html_include);
-}
-
-static void cleanup_lua_filter(struct cgit_filter *base)
-{
-	struct lua_filter *filter = (struct lua_filter *)base;
-
-	if (!filter->lua_state)
-		return;
-
-	lua_close(filter->lua_state);
-	filter->lua_state = NULL;
-	if (filter->script_file) {
-		free(filter->script_file);
-		filter->script_file = NULL;
-	}
-}
-
-static int init_lua_filter(struct lua_filter *filter)
-{
-	if (filter->lua_state)
-		return 0;
-
-	if (!(filter->lua_state = luaL_newstate()))
-		return 1;
-
-	luaL_openlibs(filter->lua_state);
-
-	lua_pushcfunction(filter->lua_state, html_lua_filter);
-	lua_setglobal(filter->lua_state, "html");
-	lua_pushcfunction(filter->lua_state, html_txt_lua_filter);
-	lua_setglobal(filter->lua_state, "html_txt");
-	lua_pushcfunction(filter->lua_state, html_attr_lua_filter);
-	lua_setglobal(filter->lua_state, "html_attr");
-	lua_pushcfunction(filter->lua_state, html_url_path_lua_filter);
-	lua_setglobal(filter->lua_state, "html_url_path");
-	lua_pushcfunction(filter->lua_state, html_url_arg_lua_filter);
-	lua_setglobal(filter->lua_state, "html_url_arg");
-	lua_pushcfunction(filter->lua_state, html_include_lua_filter);
-	lua_setglobal(filter->lua_state, "html_include");
-
-	if (luaL_dofile(filter->lua_state, filter->script_file)) {
-		error_lua_filter(filter);
-		lua_close(filter->lua_state);
-		filter->lua_state = NULL;
-		return 1;
-	}
-	return 0;
-}
-
-static int open_lua_filter(struct cgit_filter *base, va_list ap)
-{
-	struct lua_filter *filter = (struct lua_filter *)base;
-	int i;
-
-	if (init_lua_filter(filter))
-		return 1;
-
-	hook_write(base, write_lua_filter);
-
-	lua_getglobal(filter->lua_state, "filter_open");
-	for (i = 0; i < filter->base.argument_count; ++i)
-		lua_pushstring(filter->lua_state, va_arg(ap, char *));
-	if (lua_pcall(filter->lua_state, filter->base.argument_count, 0, 0)) {
-		error_lua_filter(filter);
-		return 1;
-	}
-	return 0;
-}
-
-static int close_lua_filter(struct cgit_filter *base)
-{
-	struct lua_filter *filter = (struct lua_filter *)base;
-	int ret = 0;
-
-	lua_getglobal(filter->lua_state, "filter_close");
-	if (lua_pcall(filter->lua_state, 0, 1, 0)) {
-		error_lua_filter(filter);
-		ret = -1;
-	} else {
-		ret = lua_tonumber(filter->lua_state, -1);
-		lua_pop(filter->lua_state, 1);
-	}
-
-	unhook_write();
-	return ret;
-}
-
-static void fprintf_lua_filter(struct cgit_filter *base, FILE *f, const char *prefix)
-{
-	struct lua_filter *filter = (struct lua_filter *)base;
-	fprintf(f, "%slua:%s\n", prefix, filter->script_file);
-}
-
-
-static struct cgit_filter *new_lua_filter(const char *cmd, int argument_count)
-{
-	struct lua_filter *filter;
-
-	filter = xmalloc(sizeof(*filter));
-	memset(filter, 0, sizeof(*filter));
-	filter->base.open = open_lua_filter;
-	filter->base.close = close_lua_filter;
-	filter->base.fprintf = fprintf_lua_filter;
-	filter->base.cleanup = cleanup_lua_filter;
-	filter->base.argument_count = argument_count;
-	filter->script_file = xstrdup(cmd);
-
-	return &filter->base;
-}
-
-#endif
-
-
-int cgit_open_filter(struct cgit_filter *filter, ...)
-{
-	int result;
-	va_list ap;
-	if (!filter)
-		return 0;
-	va_start(ap, filter);
-	result = filter->open(filter, ap);
-	va_end(ap);
-	return result;
-}
-
-int cgit_close_filter(struct cgit_filter *filter)
-{
-	if (!filter)
-		return 0;
-	return filter->close(filter);
-}
-
-void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix)
-{
-	filter->fprintf(filter, f, prefix);
-}
-
-
-
-static const struct {
-	const char *prefix;
-	struct cgit_filter *(*ctor)(const char *cmd, int argument_count);
-} filter_specs[] = {
-	{ "exec", new_exec_filter },
-#ifndef NO_LUA
-	{ "lua", new_lua_filter },
-#endif
-};
-
-struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype)
-{
-	char *colon;
-	int i;
-	size_t len;
-	int argument_count;
-
-	if (!cmd || !cmd[0])
-		return NULL;
-
-	colon = strchr(cmd, ':');
-	len = colon - cmd;
-	/*
-	 * In case we're running on Windows, don't allow a single letter before
-	 * the colon.
-	 */
-	if (len == 1)
-		colon = NULL;
-
-	switch (filtertype) {
-		case AUTH:
-			argument_count = 12;
-			break;
-
-		case EMAIL:
-			argument_count = 2;
-			break;
-
-		case OWNER:
-			argument_count = 0;
-			break;
-
-		case SOURCE:
-		case ABOUT:
-			argument_count = 1;
-			break;
-
-		case COMMIT:
-		default:
-			argument_count = 0;
-			break;
-	}
-
-	/* If no prefix is given, exec filter is the default. */
-	if (!colon)
-		return new_exec_filter(cmd, argument_count);
-
-	for (i = 0; i < ARRAY_SIZE(filter_specs); i++) {
-		if (len == strlen(filter_specs[i].prefix) &&
-		    !strncmp(filter_specs[i].prefix, cmd, len))
-			return filter_specs[i].ctor(colon + 1, argument_count);
-	}
-
-	die("Invalid filter type: %.*s", (int) len, cmd);
-}
diff --git a/filters/email-gravatar.lua b/filters/email-gravatar.lua
deleted file mode 100644
index c39b490d..00000000
--- a/filters/email-gravatar.lua
+++ /dev/null
@@ -1,35 +0,0 @@
--- This script may be used with the email-filter or repo.email-filter settings in cgitrc.
--- It adds gravatar icons to author names. It is designed to be used with the lua:
--- prefix in filters. It is much faster than the corresponding python script.
---
--- Requirements:
--- 	luaossl
--- 	<http://25thandclement.com/~william/projects/luaossl.html>
---
-
-local digest = require("openssl.digest")
-
-function md5_hex(input)
-	local b = digest.new("md5"):final(input)
-	local x = ""
-	for i = 1, #b do
-		x = x .. string.format("%.2x", string.byte(b, i))
-	end
-	return x
-end
-
-function filter_open(email, page)
-	buffer = ""
-	md5 = md5_hex(email:sub(2, -2):lower())
-end
-
-function filter_close()
-	html("<img src='//www.gravatar.com/avatar/" .. md5 .. "?s=13&amp;d=retro' width='13' height='13' alt='Gravatar' /> " .. buffer)
-	return 0
-end
-
-function filter_write(str)
-	buffer = buffer .. str
-end
-
-
diff --git a/filters/email-libravatar.lua b/filters/email-libravatar.lua
deleted file mode 100644
index 7336baf8..00000000
--- a/filters/email-libravatar.lua
+++ /dev/null
@@ -1,36 +0,0 @@
--- This script may be used with the email-filter or repo.email-filter settings in cgitrc.
--- It adds libravatar icons to author names. It is designed to be used with the lua:
--- prefix in filters.
---
--- Requirements:
--- 	luaossl
--- 	<http://25thandclement.com/~william/projects/luaossl.html>
---
-
-local digest = require("openssl.digest")
-
-function md5_hex(input)
-	local b = digest.new("md5"):final(input)
-	local x = ""
-	for i = 1, #b do
-		x = x .. string.format("%.2x", string.byte(b, i))
-	end
-	return x
-end
-
-function filter_open(email, page)
-	buffer = ""
-	md5 = md5_hex(email:sub(2, -2):lower())
-end
-
-function filter_close()
-	baseurl = os.getenv("HTTPS") and "https://seccdn.libravatar.org/" or "http://cdn.libravatar.org/"
-	html("<img src='" .. baseurl .. "avatar/" .. md5 .. "?s=13&amp;d=retro' width='13' height='13' alt='Libravatar' /> " .. buffer)
-	return 0
-end
-
-function filter_write(str)
-	buffer = buffer .. str
-end
-
-
diff --git a/filters/file-authentication.lua b/filters/file-authentication.lua
deleted file mode 100644
index 02488046..00000000
--- a/filters/file-authentication.lua
+++ /dev/null
@@ -1,359 +0,0 @@
--- This script may be used with the auth-filter.
---
--- Requirements:
--- 	luaossl
--- 	<http://25thandclement.com/~william/projects/luaossl.html>
--- 	luaposix
--- 	<https://github.com/luaposix/luaposix>
---
-local sysstat = require("posix.sys.stat")
-local unistd = require("posix.unistd")
-local rand = require("openssl.rand")
-local hmac = require("openssl.hmac")
-
--- This file should contain a series of lines in the form of:
---	username1:hash1
---	username2:hash2
---	username3:hash3
---	...
--- Hashes can be generated using something like `mkpasswd -m sha-512 -R 300000`.
--- This file should not be world-readable.
-local users_filename = "/etc/cgit-auth/users"
-
--- This file should contain a series of lines in the form of:
--- 	groupname1:username1,username2,username3,...
---	...
-local groups_filename = "/etc/cgit-auth/groups"
-
--- This file should contain a series of lines in the form of:
--- 	reponame1:groupname1,groupname2,groupname3,...
---	...
-local repos_filename = "/etc/cgit-auth/repos"
-
--- Set this to a path this script can write to for storing a persistent
--- cookie secret, which should not be world-readable.
-local secret_filename = "/var/cache/cgit/auth-secret"
-
---
---
--- Authentication functions follow below. Swap these out if you want different authentication semantics.
---
---
-
--- Looks up a hash for a given user.
-function lookup_hash(user)
-	local line
-	for line in io.lines(users_filename) do
-		local u, h = string.match(line, "(.-):(.+)")
-		if u:lower() == user:lower() then
-			return h
-		end
-	end
-	return nil
-end
-
--- Looks up users for a given repo.
-function lookup_users(repo)
-	local users = nil
-	local groups = nil
-	local line, group, user
-	for line in io.lines(repos_filename) do
-		local r, g = string.match(line, "(.-):(.+)")
-		if r == repo then
-			groups = { }
-			for group in string.gmatch(g, "([^,]+)") do
-				groups[group:lower()] = true
-			end
-			break
-		end
-	end
-	if groups == nil then
-		return nil
-	end
-	for line in io.lines(groups_filename) do
-		local g, u = string.match(line, "(.-):(.+)")
-		if groups[g:lower()] then
-			if users == nil then
-				users = { }
-			end
-			for user in string.gmatch(u, "([^,]+)") do
-				users[user:lower()] = true
-			end
-		end
-	end
-	return users
-end
-
-
--- Sets HTTP cookie headers based on post and sets up redirection.
-function authenticate_post()
-	local hash = lookup_hash(post["username"])
-	local redirect = validate_value("redirect", post["redirect"])
-
-	if redirect == nil then
-		not_found()
-		return 0
-	end
-
-	redirect_to(redirect)
-
-	if hash == nil or hash ~= unistd.crypt(post["password"], hash) then
-		set_cookie("cgitauth", "")
-	else
-		-- One week expiration time
-		local username = secure_value("username", post["username"], os.time() + 604800)
-		set_cookie("cgitauth", username)
-	end
-
-	html("\n")
-	return 0
-end
-
-
--- Returns 1 if the cookie is valid and 0 if it is not.
-function authenticate_cookie()
-	accepted_users = lookup_users(cgit["repo"])
-	if accepted_users == nil then
-		-- We return as valid if the repo is not protected.
-		return 1
-	end
-
-	local username = validate_value("username", get_cookie(http["cookie"], "cgitauth"))
-	if username == nil or not accepted_users[username:lower()] then
-		return 0
-	else
-		return 1
-	end
-end
-
--- Prints the html for the login form.
-function body()
-	html("<h2>Authentication Required</h2>")
-	html("<form method='post' action='")
-	html_attr(cgit["login"])
-	html("'>")
-	html("<input type='hidden' name='redirect' value='")
-	html_attr(secure_value("redirect", cgit["url"], 0))
-	html("' />")
-	html("<table>")
-	html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>")
-	html("<tr><td><label for='password'>Password:</label></td><td><input id='password' name='password' type='password' /></td></tr>")
-	html("<tr><td colspan='2'><input value='Login' type='submit' /></td></tr>")
-	html("</table></form>")
-
-	return 0
-end
-
-
-
---
---
--- Wrapper around filter API, exposing the http table, the cgit table, and the post table to the above functions.
---
---
-
-local actions = {}
-actions["authenticate-post"] = authenticate_post
-actions["authenticate-cookie"] = authenticate_cookie
-actions["body"] = body
-
-function filter_open(...)
-	action = actions[select(1, ...)]
-
-	http = {}
-	http["cookie"] = select(2, ...)
-	http["method"] = select(3, ...)
-	http["query"] = select(4, ...)
-	http["referer"] = select(5, ...)
-	http["path"] = select(6, ...)
-	http["host"] = select(7, ...)
-	http["https"] = select(8, ...)
-
-	cgit = {}
-	cgit["repo"] = select(9, ...)
-	cgit["page"] = select(10, ...)
-	cgit["url"] = select(11, ...)
-	cgit["login"] = select(12, ...)
-
-end
-
-function filter_close()
-	return action()
-end
-
-function filter_write(str)
-	post = parse_qs(str)
-end
-
-
---
---
--- Utility functions based on keplerproject/wsapi.
---
---
-
-function url_decode(str)
-	if not str then
-		return ""
-	end
-	str = string.gsub(str, "+", " ")
-	str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
-	str = string.gsub(str, "\r\n", "\n")
-	return str
-end
-
-function url_encode(str)
-	if not str then
-		return ""
-	end
-	str = string.gsub(str, "\n", "\r\n")
-	str = string.gsub(str, "([^%w ])", function(c) return string.format("%%%02X", string.byte(c)) end)
-	str = string.gsub(str, " ", "+")
-	return str
-end
-
-function parse_qs(qs)
-	local tab = {}
-	for key, val in string.gmatch(qs, "([^&=]+)=([^&=]*)&?") do
-		tab[url_decode(key)] = url_decode(val)
-	end
-	return tab
-end
-
-function get_cookie(cookies, name)
-	cookies = string.gsub(";" .. cookies .. ";", "%s*;%s*", ";")
-	return url_decode(string.match(cookies, ";" .. name .. "=(.-);"))
-end
-
-function tohex(b)
-	local x = ""
-	for i = 1, #b do
-		x = x .. string.format("%.2x", string.byte(b, i))
-	end
-	return x
-end
-
---
---
--- Cookie construction and validation helpers.
---
---
-
-local secret = nil
-
--- Loads a secret from a file, creates a secret, or returns one from memory.
-function get_secret()
-	if secret ~= nil then
-		return secret
-	end
-	local secret_file = io.open(secret_filename, "r")
-	if secret_file == nil then
-		local old_umask = sysstat.umask(63)
-		local temporary_filename = secret_filename .. ".tmp." .. tohex(rand.bytes(16))
-		local temporary_file = io.open(temporary_filename, "w")
-		if temporary_file == nil then
-			os.exit(177)
-		end
-		temporary_file:write(tohex(rand.bytes(32)))
-		temporary_file:close()
-		unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
-		unistd.unlink(temporary_filename)
-		sysstat.umask(old_umask)
-		secret_file = io.open(secret_filename, "r")
-	end
-	if secret_file == nil then
-		os.exit(177)
-	end
-	secret = secret_file:read()
-	secret_file:close()
-	if secret:len() ~= 64 then
-		os.exit(177)
-	end
-	return secret
-end
-
--- Returns value of cookie if cookie is valid. Otherwise returns nil.
-function validate_value(expected_field, cookie)
-	local i = 0
-	local value = ""
-	local field = ""
-	local expiration = 0
-	local salt = ""
-	local chmac = ""
-
-	if cookie == nil or cookie:len() < 3 or cookie:sub(1, 1) == "|" then
-		return nil
-	end
-
-	for component in string.gmatch(cookie, "[^|]+") do
-		if i == 0 then
-			field = component
-		elseif i == 1 then
-			value = component
-		elseif i == 2 then
-			expiration = tonumber(component)
-			if expiration == nil then
-				expiration = -1
-			end
-		elseif i == 3 then
-			salt = component
-		elseif i == 4 then
-			chmac = component
-		else
-			break
-		end
-		i = i + 1
-	end
-
-	if chmac == nil or chmac:len() == 0 then
-		return nil
-	end
-
-	-- Lua hashes strings, so these comparisons are time invariant.
-	if chmac ~= tohex(hmac.new(get_secret(), "sha256"):final(field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt)) then
-		return nil
-	end
-
-	if expiration == -1 or (expiration ~= 0 and expiration <= os.time()) then
-		return nil
-	end
-
-	if url_decode(field) ~= expected_field then
-		return nil
-	end
-
-	return url_decode(value)
-end
-
-function secure_value(field, value, expiration)
-	if value == nil or value:len() <= 0 then
-		return ""
-	end
-
-	local authstr = ""
-	local salt = tohex(rand.bytes(16))
-	value = url_encode(value)
-	field = url_encode(field)
-	authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
-	authstr = authstr .. "|" .. tohex(hmac.new(get_secret(), "sha256"):final(authstr))
-	return authstr
-end
-
-function set_cookie(cookie, value)
-	html("Set-Cookie: " .. cookie .. "=" .. value .. "; HttpOnly")
-	if http["https"] == "yes" or http["https"] == "on" or http["https"] == "1" then
-		html("; secure")
-	end
-	html("\n")
-end
-
-function redirect_to(url)
-	html("Status: 302 Redirect\n")
-	html("Cache-Control: no-cache, no-store\n")
-	html("Location: " .. url .. "\n")
-end
-
-function not_found()
-	html("Status: 404 Not Found\n")
-	html("Cache-Control: no-cache, no-store\n\n")
-end
diff --git a/filters/gentoo-ldap-authentication.lua b/filters/gentoo-ldap-authentication.lua
deleted file mode 100644
index 673c88d1..00000000
--- a/filters/gentoo-ldap-authentication.lua
+++ /dev/null
@@ -1,360 +0,0 @@
--- This script may be used with the auth-filter. Be sure to configure it as you wish.
---
--- Requirements:
--- 	luaossl
--- 	<http://25thandclement.com/~william/projects/luaossl.html>
--- 	lualdap >= 1.2
--- 	<https://git.zx2c4.com/lualdap/about/>
--- 	luaposix
--- 	<https://github.com/luaposix/luaposix>
---
-local sysstat = require("posix.sys.stat")
-local unistd = require("posix.unistd")
-local lualdap = require("lualdap")
-local rand = require("openssl.rand")
-local hmac = require("openssl.hmac")
-
---
---
--- Configure these variables for your settings.
---
---
-
--- A list of password protected repositories, with which gentooAccess
--- group is allowed to access each one.
-local protected_repos = {
-	glouglou = "infra",
-	portage = "dev"
-}
-
--- Set this to a path this script can write to for storing a persistent
--- cookie secret, which should be guarded.
-local secret_filename = "/var/cache/cgit/auth-secret"
-
-
---
---
--- Authentication functions follow below. Swap these out if you want different authentication semantics.
---
---
-
--- Sets HTTP cookie headers based on post and sets up redirection.
-function authenticate_post()
-	local redirect = validate_value("redirect", post["redirect"])
-
-	if redirect == nil then
-		not_found()
-		return 0
-	end
-
-	redirect_to(redirect)
-	
-	local groups = gentoo_ldap_user_groups(post["username"], post["password"])
-	if groups == nil then
-		set_cookie("cgitauth", "")
-	else
-		-- One week expiration time
-		set_cookie("cgitauth", secure_value("gentoogroups", table.concat(groups, ","), os.time() + 604800))
-	end
-
-	html("\n")
-	return 0
-end
-
-
--- Returns 1 if the cookie is valid and 0 if it is not.
-function authenticate_cookie()
-	local required_group = protected_repos[cgit["repo"]]
-	if required_group == nil then
-		-- We return as valid if the repo is not protected.
-		return 1
-	end
-	
-	local user_groups = validate_value("gentoogroups", get_cookie(http["cookie"], "cgitauth"))
-	if user_groups == nil or user_groups == "" then
-		return 0
-	end
-	for group in string.gmatch(user_groups, "[^,]+") do
-		if group == required_group then
-			return 1
-		end
-	end
-	return 0
-end
-
--- Prints the html for the login form.
-function body()
-	html("<h2>Gentoo LDAP Authentication Required</h2>")
-	html("<form method='post' action='")
-	html_attr(cgit["login"])
-	html("'>")
-	html("<input type='hidden' name='redirect' value='")
-	html_attr(secure_value("redirect", cgit["url"], 0))
-	html("' />")
-	html("<table>")
-	html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>")
-	html("<tr><td><label for='password'>Password:</label></td><td><input id='password' name='password' type='password' /></td></tr>")
-	html("<tr><td colspan='2'><input value='Login' type='submit' /></td></tr>")
-	html("</table></form>")
-
-	return 0
-end
-
---
---
--- Gentoo LDAP support.
---
---
-
-function gentoo_ldap_user_groups(username, password)
-	-- Ensure the user is alphanumeric
-	if username == nil or username:match("%W") then
-		return nil
-	end
-
-	local who = "uid=" .. username .. ",ou=devs,dc=gentoo,dc=org"
-
-	local ldap, err = lualdap.open_simple {
-		uri = "ldap://ldap1.gentoo.org",
-		who = who,
-		password = password,
-		starttls = true,
-		certfile = "/var/www/uwsgi/cgit/gentoo-ldap/star.gentoo.org.crt",
-		keyfile = "/var/www/uwsgi/cgit/gentoo-ldap/star.gentoo.org.key",
-		cacertfile = "/var/www/uwsgi/cgit/gentoo-ldap/ca.pem"
-	}
-	if ldap == nil then
-		return nil
-	end
-
-	local group_suffix = ".group"
-	local group_suffix_len = group_suffix:len()
-	local groups = {}
-	for dn, attribs in ldap:search { base = who, scope = "subtree" } do
-		local access = attribs["gentooAccess"]
-		if dn == who and access ~= nil then
-			for i, v in ipairs(access) do
-				local vlen = v:len()
-				if vlen > group_suffix_len and v:sub(-group_suffix_len) == group_suffix then
-					table.insert(groups, v:sub(1, vlen - group_suffix_len))
-				end
-			end
-		end
-	end
-
-	ldap:close()
-
-	return groups
-end
-
---
---
--- Wrapper around filter API, exposing the http table, the cgit table, and the post table to the above functions.
---
---
-
-local actions = {}
-actions["authenticate-post"] = authenticate_post
-actions["authenticate-cookie"] = authenticate_cookie
-actions["body"] = body
-
-function filter_open(...)
-	action = actions[select(1, ...)]
-
-	http = {}
-	http["cookie"] = select(2, ...)
-	http["method"] = select(3, ...)
-	http["query"] = select(4, ...)
-	http["referer"] = select(5, ...)
-	http["path"] = select(6, ...)
-	http["host"] = select(7, ...)
-	http["https"] = select(8, ...)
-
-	cgit = {}
-	cgit["repo"] = select(9, ...)
-	cgit["page"] = select(10, ...)
-	cgit["url"] = select(11, ...)
-	cgit["login"] = select(12, ...)
-
-end
-
-function filter_close()
-	return action()
-end
-
-function filter_write(str)
-	post = parse_qs(str)
-end
-
-
---
---
--- Utility functions based on keplerproject/wsapi.
---
---
-
-function url_decode(str)
-	if not str then
-		return ""
-	end
-	str = string.gsub(str, "+", " ")
-	str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
-	str = string.gsub(str, "\r\n", "\n")
-	return str
-end
-
-function url_encode(str)
-	if not str then
-		return ""
-	end
-	str = string.gsub(str, "\n", "\r\n")
-	str = string.gsub(str, "([^%w ])", function(c) return string.format("%%%02X", string.byte(c)) end)
-	str = string.gsub(str, " ", "+")
-	return str
-end
-
-function parse_qs(qs)
-	local tab = {}
-	for key, val in string.gmatch(qs, "([^&=]+)=([^&=]*)&?") do
-		tab[url_decode(key)] = url_decode(val)
-	end
-	return tab
-end
-
-function get_cookie(cookies, name)
-	cookies = string.gsub(";" .. cookies .. ";", "%s*;%s*", ";")
-	return string.match(cookies, ";" .. name .. "=(.-);")
-end
-
-function tohex(b)
-	local x = ""
-	for i = 1, #b do
-		x = x .. string.format("%.2x", string.byte(b, i))
-	end
-	return x
-end
-
---
---
--- Cookie construction and validation helpers.
---
---
-
-local secret = nil
-
--- Loads a secret from a file, creates a secret, or returns one from memory.
-function get_secret()
-	if secret ~= nil then
-		return secret
-	end
-	local secret_file = io.open(secret_filename, "r")
-	if secret_file == nil then
-		local old_umask = sysstat.umask(63)
-		local temporary_filename = secret_filename .. ".tmp." .. tohex(rand.bytes(16))
-		local temporary_file = io.open(temporary_filename, "w")
-		if temporary_file == nil then
-			os.exit(177)
-		end
-		temporary_file:write(tohex(rand.bytes(32)))
-		temporary_file:close()
-		unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
-		unistd.unlink(temporary_filename)
-		sysstat.umask(old_umask)
-		secret_file = io.open(secret_filename, "r")
-	end
-	if secret_file == nil then
-		os.exit(177)
-	end
-	secret = secret_file:read()
-	secret_file:close()
-	if secret:len() ~= 64 then
-		os.exit(177)
-	end
-	return secret
-end
-
--- Returns value of cookie if cookie is valid. Otherwise returns nil.
-function validate_value(expected_field, cookie)
-	local i = 0
-	local value = ""
-	local field = ""
-	local expiration = 0
-	local salt = ""
-	local chmac = ""
-
-	if cookie == nil or cookie:len() < 3 or cookie:sub(1, 1) == "|" then
-		return nil
-	end
-
-	for component in string.gmatch(cookie, "[^|]+") do
-		if i == 0 then
-			field = component
-		elseif i == 1 then
-			value = component
-		elseif i == 2 then
-			expiration = tonumber(component)
-			if expiration == nil then
-				expiration = -1
-			end
-		elseif i == 3 then
-			salt = component
-		elseif i == 4 then
-			chmac = component
-		else
-			break
-		end
-		i = i + 1
-	end
-
-	if chmac == nil or chmac:len() == 0 then
-		return nil
-	end
-
-	-- Lua hashes strings, so these comparisons are time invariant.
-	if chmac ~= tohex(hmac.new(get_secret(), "sha256"):final(field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt)) then
-		return nil
-	end
-
-	if expiration == -1 or (expiration ~= 0 and expiration <= os.time()) then
-		return nil
-	end
-
-	if url_decode(field) ~= expected_field then
-		return nil
-	end
-
-	return url_decode(value)
-end
-
-function secure_value(field, value, expiration)
-	if value == nil or value:len() <= 0 then
-		return ""
-	end
-
-	local authstr = ""
-	local salt = tohex(rand.bytes(16))
-	value = url_encode(value)
-	field = url_encode(field)
-	authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
-	authstr = authstr .. "|" .. tohex(hmac.new(get_secret(), "sha256"):final(authstr))
-	return authstr
-end
-
-function set_cookie(cookie, value)
-	html("Set-Cookie: " .. cookie .. "=" .. value .. "; HttpOnly")
-	if http["https"] == "yes" or http["https"] == "on" or http["https"] == "1" then
-		html("; secure")
-	end
-	html("\n")
-end
-
-function redirect_to(url)
-	html("Status: 302 Redirect\n")
-	html("Cache-Control: no-cache, no-store\n")
-	html("Location: " .. url .. "\n")
-end
-
-function not_found()
-	html("Status: 404 Not Found\n")
-	html("Cache-Control: no-cache, no-store\n\n")
-end
diff --git a/filters/owner-example.lua b/filters/owner-example.lua
deleted file mode 100644
index 50fc25a8..00000000
--- a/filters/owner-example.lua
+++ /dev/null
@@ -1,17 +0,0 @@
--- This script is an example of an owner-filter.  It replaces the
--- usual query link with one to a fictional homepage.  This script may
--- be used with the owner-filter or repo.owner-filter settings in
--- cgitrc with the `lua:` prefix.
-
-function filter_open()
-	buffer = ""
-end
-
-function filter_close()
-	html(string.format("<a href=\"%s\">%s</a>", "http://wiki.example.com/about/" .. buffer, buffer))
-	return 0
-end
-
-function filter_write(str)
-	buffer = buffer .. str
-end
diff --git a/filters/simple-authentication.lua b/filters/simple-authentication.lua
deleted file mode 100644
index 23d34576..00000000
--- a/filters/simple-authentication.lua
+++ /dev/null
@@ -1,314 +0,0 @@
--- This script may be used with the auth-filter. Be sure to configure it as you wish.
---
--- Requirements:
--- 	luaossl
--- 	<http://25thandclement.com/~william/projects/luaossl.html>
--- 	luaposix
--- 	<https://github.com/luaposix/luaposix>
---
-local sysstat = require("posix.sys.stat")
-local unistd = require("posix.unistd")
-local rand = require("openssl.rand")
-local hmac = require("openssl.hmac")
-
---
---
--- Configure these variables for your settings.
---
---
-
--- A list of password protected repositories along with the users who can access them.
-local protected_repos = {
-	glouglou	= { laurent = true, jason = true },
-	qt		= { jason = true, bob = true }
-}
-
--- A list of users and hashes, generated with `mkpasswd -m sha-512 -R 300000`.
-local users = {
-	jason		= "$6$rounds=300000$YYJct3n/o.ruYK$HhpSeuCuW1fJkpvMZOZzVizeLsBKcGA/aF2UPuV5v60JyH2MVSG6P511UMTj2F3H75.IT2HIlnvXzNb60FcZH1",
-	laurent		= "$6$rounds=300000$dP0KNHwYb3JKigT$pN/LG7rWxQ4HniFtx5wKyJXBJUKP7R01zTNZ0qSK/aivw8ywGAOdfYiIQFqFhZFtVGvr11/7an.nesvm8iJUi.",
-	bob		= "$6$rounds=300000$jCLCCt6LUpTz$PI1vvd1yaVYcCzqH8QAJFcJ60b6W/6sjcOsU7mAkNo7IE8FRGW1vkjF8I/T5jt/auv5ODLb1L4S2s.CAyZyUC"
-}
-
--- Set this to a path this script can write to for storing a persistent
--- cookie secret, which should be guarded.
-local secret_filename = "/var/cache/cgit/auth-secret"
-
---
---
--- Authentication functions follow below. Swap these out if you want different authentication semantics.
---
---
-
--- Sets HTTP cookie headers based on post and sets up redirection.
-function authenticate_post()
-	local hash = users[post["username"]]
-	local redirect = validate_value("redirect", post["redirect"])
-
-	if redirect == nil then
-		not_found()
-		return 0
-	end
-
-	redirect_to(redirect)
-
-	if hash == nil or hash ~= unistd.crypt(post["password"], hash) then
-		set_cookie("cgitauth", "")
-	else
-		-- One week expiration time
-		local username = secure_value("username", post["username"], os.time() + 604800)
-		set_cookie("cgitauth", username)
-	end
-
-	html("\n")
-	return 0
-end
-
-
--- Returns 1 if the cookie is valid and 0 if it is not.
-function authenticate_cookie()
-	accepted_users = protected_repos[cgit["repo"]]
-	if accepted_users == nil then
-		-- We return as valid if the repo is not protected.
-		return 1
-	end
-
-	local username = validate_value("username", get_cookie(http["cookie"], "cgitauth"))
-	if username == nil or not accepted_users[username:lower()] then
-		return 0
-	else
-		return 1
-	end
-end
-
--- Prints the html for the login form.
-function body()
-	html("<h2>Authentication Required</h2>")
-	html("<form method='post' action='")
-	html_attr(cgit["login"])
-	html("'>")
-	html("<input type='hidden' name='redirect' value='")
-	html_attr(secure_value("redirect", cgit["url"], 0))
-	html("' />")
-	html("<table>")
-	html("<tr><td><label for='username'>Username:</label></td><td><input id='username' name='username' autofocus /></td></tr>")
-	html("<tr><td><label for='password'>Password:</label></td><td><input id='password' name='password' type='password' /></td></tr>")
-	html("<tr><td colspan='2'><input value='Login' type='submit' /></td></tr>")
-	html("</table></form>")
-
-	return 0
-end
-
-
-
---
---
--- Wrapper around filter API, exposing the http table, the cgit table, and the post table to the above functions.
---
---
-
-local actions = {}
-actions["authenticate-post"] = authenticate_post
-actions["authenticate-cookie"] = authenticate_cookie
-actions["body"] = body
-
-function filter_open(...)
-	action = actions[select(1, ...)]
-
-	http = {}
-	http["cookie"] = select(2, ...)
-	http["method"] = select(3, ...)
-	http["query"] = select(4, ...)
-	http["referer"] = select(5, ...)
-	http["path"] = select(6, ...)
-	http["host"] = select(7, ...)
-	http["https"] = select(8, ...)
-
-	cgit = {}
-	cgit["repo"] = select(9, ...)
-	cgit["page"] = select(10, ...)
-	cgit["url"] = select(11, ...)
-	cgit["login"] = select(12, ...)
-
-end
-
-function filter_close()
-	return action()
-end
-
-function filter_write(str)
-	post = parse_qs(str)
-end
-
-
---
---
--- Utility functions based on keplerproject/wsapi.
---
---
-
-function url_decode(str)
-	if not str then
-		return ""
-	end
-	str = string.gsub(str, "+", " ")
-	str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end)
-	str = string.gsub(str, "\r\n", "\n")
-	return str
-end
-
-function url_encode(str)
-	if not str then
-		return ""
-	end
-	str = string.gsub(str, "\n", "\r\n")
-	str = string.gsub(str, "([^%w ])", function(c) return string.format("%%%02X", string.byte(c)) end)
-	str = string.gsub(str, " ", "+")
-	return str
-end
-
-function parse_qs(qs)
-	local tab = {}
-	for key, val in string.gmatch(qs, "([^&=]+)=([^&=]*)&?") do
-		tab[url_decode(key)] = url_decode(val)
-	end
-	return tab
-end
-
-function get_cookie(cookies, name)
-	cookies = string.gsub(";" .. cookies .. ";", "%s*;%s*", ";")
-	return url_decode(string.match(cookies, ";" .. name .. "=(.-);"))
-end
-
-function tohex(b)
-	local x = ""
-	for i = 1, #b do
-		x = x .. string.format("%.2x", string.byte(b, i))
-	end
-	return x
-end
-
---
---
--- Cookie construction and validation helpers.
---
---
-
-local secret = nil
-
--- Loads a secret from a file, creates a secret, or returns one from memory.
-function get_secret()
-	if secret ~= nil then
-		return secret
-	end
-	local secret_file = io.open(secret_filename, "r")
-	if secret_file == nil then
-		local old_umask = sysstat.umask(63)
-		local temporary_filename = secret_filename .. ".tmp." .. tohex(rand.bytes(16))
-		local temporary_file = io.open(temporary_filename, "w")
-		if temporary_file == nil then
-			os.exit(177)
-		end
-		temporary_file:write(tohex(rand.bytes(32)))
-		temporary_file:close()
-		unistd.link(temporary_filename, secret_filename) -- Intentionally fails in the case that another process is doing the same.
-		unistd.unlink(temporary_filename)
-		sysstat.umask(old_umask)
-		secret_file = io.open(secret_filename, "r")
-	end
-	if secret_file == nil then
-		os.exit(177)
-	end
-	secret = secret_file:read()
-	secret_file:close()
-	if secret:len() ~= 64 then
-		os.exit(177)
-	end
-	return secret
-end
-
--- Returns value of cookie if cookie is valid. Otherwise returns nil.
-function validate_value(expected_field, cookie)
-	local i = 0
-	local value = ""
-	local field = ""
-	local expiration = 0
-	local salt = ""
-	local chmac = ""
-
-	if cookie == nil or cookie:len() < 3 or cookie:sub(1, 1) == "|" then
-		return nil
-	end
-
-	for component in string.gmatch(cookie, "[^|]+") do
-		if i == 0 then
-			field = component
-		elseif i == 1 then
-			value = component
-		elseif i == 2 then
-			expiration = tonumber(component)
-			if expiration == nil then
-				expiration = -1
-			end
-		elseif i == 3 then
-			salt = component
-		elseif i == 4 then
-			chmac = component
-		else
-			break
-		end
-		i = i + 1
-	end
-
-	if chmac == nil or chmac:len() == 0 then
-		return nil
-	end
-
-	-- Lua hashes strings, so these comparisons are time invariant.
-	if chmac ~= tohex(hmac.new(get_secret(), "sha256"):final(field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt)) then
-		return nil
-	end
-
-	if expiration == -1 or (expiration ~= 0 and expiration <= os.time()) then
-		return nil
-	end
-
-	if url_decode(field) ~= expected_field then
-		return nil
-	end
-
-	return url_decode(value)
-end
-
-function secure_value(field, value, expiration)
-	if value == nil or value:len() <= 0 then
-		return ""
-	end
-
-	local authstr = ""
-	local salt = tohex(rand.bytes(16))
-	value = url_encode(value)
-	field = url_encode(field)
-	authstr = field .. "|" .. value .. "|" .. tostring(expiration) .. "|" .. salt
-	authstr = authstr .. "|" .. tohex(hmac.new(get_secret(), "sha256"):final(authstr))
-	return authstr
-end
-
-function set_cookie(cookie, value)
-	html("Set-Cookie: " .. cookie .. "=" .. value .. "; HttpOnly")
-	if http["https"] == "yes" or http["https"] == "on" or http["https"] == "1" then
-		html("; secure")
-	end
-	html("\n")
-end
-
-function redirect_to(url)
-	html("Status: 302 Redirect\n")
-	html("Cache-Control: no-cache, no-store\n")
-	html("Location: " .. url .. "\n")
-end
-
-function not_found()
-	html("Status: 404 Not Found\n")
-	html("Cache-Control: no-cache, no-store\n\n")
-end
diff --git a/git b/git
deleted file mode 160000
-Subproject ebf3c04b262aa27fbb97f8a0156c2347fecafaf
diff --git a/gpl.c b/gpl.c
new file mode 100644
index 00000000..c0c58e1e
--- /dev/null
+++ b/gpl.c
@@ -0,0 +1,20 @@
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sysexits.h>
diff --git a/home/.config/X/modmap b/home/.config/X/modmap
new file mode 100644
index 00000000..b0b1ea79
--- /dev/null
+++ b/home/.config/X/modmap
@@ -0,0 +1,16 @@
+clear Lock
+keysym Caps_Lock = Escape
+keysym 1 = exclam 1
+keysym 2 = at 2
+keysym 3 = numbersign 3
+keysym 4 = dollar 4
+keysym 5 = percent 5
+keysym 6 = asciicircum 6
+keysym 7 = ampersand 7
+keysym 8 = asterisk 8
+keysym 9 = parenleft 9
+keysym 0 = parenright 0
+keysym minus = underscore minus
+keysym bracketleft = braceleft bracketleft
+keysym bracketright = braceright bracketright
+keysym backslash = bar backslash
diff --git a/home/.config/X/resources b/home/.config/X/resources
new file mode 100644
index 00000000..44b8e791
--- /dev/null
+++ b/home/.config/X/resources
@@ -0,0 +1,49 @@
+Xft.dpi: 144
+Xft.antialias: true
+Xft.hinting: false
+
+Xcursor.size: 64
+Xcursor.theme: dmz-aa
+
+XLock.usefirst: false
+XLock.echokeys: true
+
+*Background: rgb:14/13/0E
+*Foreground: rgb:B7/A9/80
+*BorderColor: rgb:99/8D/6B
+
+XTerm*utf8: true
+XTerm*metaSendsEscape: true
+XTerm*alternateScroll: true
+XTerm*allowMouseOps: false
+XTerm*bellIsUrgent: true
+XTerm*charClass: 33:48,36-47:48,58-59:48,61:48,63-64:48,95:48,126:48
+
+XTerm*VT100*translations: #override \n\
+	Super <Key>C: copy-selection(CLIPBOARD) \n\
+	Super <Key>V: insert-selection(CLIPBOARD)
+
+XTerm*faceName: Go Mono:size=11
+XTerm*internalBorder: 6
+XTerm*colorBDMode: true
+XTerm*scrollBar: false
+XTerm*pointerMode: 2
+
+XTerm*color0: rgb:16/15/10
+XTerm*color1: rgb:A3/28/10
+XTerm*color2: rgb:72/7A/18
+XTerm*color3: rgb:A3/77/20
+XTerm*color4: rgb:3D/62/66
+XTerm*color5: rgb:7A/49/55
+XTerm*color6: rgb:55/7A/55
+XTerm*color7: rgb:99/8D/6B
+XTerm*color8: rgb:4C/46/35
+XTerm*color9: rgb:CC/32/14
+XTerm*color10: rgb:8E/99/1E
+XTerm*color11: rgb:CC/95/28
+XTerm*color12: rgb:4C/7B/7F
+XTerm*color13: rgb:99/5B/6B
+XTerm*color14: rgb:6B/99/6B
+XTerm*color15: rgb:CC/BC/8E
+XTerm*colorBD: rgb:CC/BC/8E
+XTerm*cursorColor: rgb:7A/71/55
diff --git a/home/.config/cwm/cwmrc b/home/.config/cwm/cwmrc
new file mode 100644
index 00000000..d72ec163
--- /dev/null
+++ b/home/.config/cwm/cwmrc
@@ -0,0 +1,87 @@
+sticky yes
+snapdist 10
+moveamount 10
+
+ignore clock
+autogroup 0 clock,XTerm
+gap 38 0 0 0
+
+unbind-key all
+bind-key 4-n terminal
+bind-key 4-t "firefox -new-tab about:blank"
+bind-key 4-Delete lock
+bind-key 4-Down window-lower
+bind-key 4-Up window-raise
+bind-key 4-slash menu-window
+bind-key 4-Tab group-cycle
+bind-key 4S-Tab group-rcycle
+bind-key 4-grave window-cycle
+bind-key 4S-grave window-rcycle
+bind-key 4-w window-close
+bind-key 4-exclam group-only-1
+bind-key 4-at group-only-2
+bind-key 4-numbersign group-only-3
+bind-key 4-dollar group-only-4
+bind-key 4-percent group-only-5
+bind-key 4-asciicircum group-only-6
+bind-key 4-ampersand group-only-7
+bind-key 4-asterisk group-only-8
+bind-key 4-parenleft group-only-9
+bind-key 4S-exclam window-movetogroup-1
+bind-key 4S-at window-movetogroup-2
+bind-key 4S-numbersign window-movetogroup-3
+bind-key 4S-dollar window-movetogroup-4
+bind-key 4S-percent window-movetogroup-5
+bind-key 4S-asciicircum window-movetogroup-6
+bind-key 4S-ampersand window-movetogroup-7
+bind-key 4S-asterisk window-movetogroup-8
+bind-key 4S-parenleft window-movetogroup-9
+bind-key 4-f window-fullscreen
+bind-key 4-m window-maximize
+bind-key 4-equal window-vmaximize
+bind-key 4S-equal window-hmaximize
+bind-key 4-underscore window-vtile
+bind-key 4S-underscore window-htile
+bind-key 4-h window-move-left-big
+bind-key 4-j window-move-down-big
+bind-key 4-k window-move-up-big
+bind-key 4-l window-move-right-big
+bind-key 4S-h window-move-left
+bind-key 4S-j window-move-down
+bind-key 4S-k window-move-up
+bind-key 4S-l window-move-right
+bind-key 4S-y window-snap-up-left
+bind-key 4S-u window-snap-up-right
+bind-key 4S-b window-snap-down-left
+bind-key 4S-n window-snap-down-right
+bind-key 4M-h window-resize-left
+bind-key 4M-j window-resize-down
+bind-key 4M-k window-resize-up
+bind-key 4M-l window-resize-right
+bind-key 4MS-h window-resize-left-big
+bind-key 4MS-j window-resize-down-big
+bind-key 4MS-k window-resize-up-big
+bind-key 4MS-l window-resize-right-big
+bind-key 4-space menu-exec
+bind-key 4S-r restart
+bind-key 4S-q quit
+
+bind-key F1 "xbacklight -steps 1 -5"
+bind-key F2 "xbacklight -steps 1 +5"
+bind-key F10 "sndioctl output.mute=!"
+bind-key F11 "sndioctl output.level=-0.05"
+bind-key F12 "sndioctl output.level=+0.05"
+
+unbind-mouse all
+bind-mouse 4-1 window-move
+bind-mouse 4S-1 window-resize
+
+fontname "Go Mono:size=11"
+borderwidth 2
+color inactiveborder rgb:4C/46/35
+color activeborder rgb:99/8D/6B
+color urgencyborder rgb:A3/77/20
+color menubg rgb:14/13/0E
+color menufg rgb:B7/A9/80
+color font rgb:B7/A9/80
+color selfont rgb:14/13/0E
diff --git a/home/.config/git/config b/home/.config/git/config
new file mode 100644
index 00000000..119180ab
--- /dev/null
+++ b/home/.config/git/config
@@ -0,0 +1,24 @@
+[user]
+	name = June McEnroe
+	email = june@causal.agency
+
+[commit]
+	verbose = true
+
+[diff]
+	colorMoved = default
+
+[merge]
+	conflictStyle = diff3
+
+[pull]
+	rebase = true
+
+[rebase]
+	autosquash = true
+
+[pretty]
+	log = %Cred%h %Creset%s%C(yellow)%d %Cgreen(%ar) %Cblue<%aN>
+
+[include]
+	path = ./private
diff --git a/home/.config/git/ignore b/home/.config/git/ignore
new file mode 100644
index 00000000..fea54519
--- /dev/null
+++ b/home/.config/git/ignore
@@ -0,0 +1,2 @@
+*.DS_store
+*.dSYM/
diff --git a/home/.config/htop/htoprc b/home/.config/htop/htoprc
new file mode 100644
index 00000000..cdda268d
--- /dev/null
+++ b/home/.config/htop/htoprc
@@ -0,0 +1,29 @@
+# Beware! This file is rewritten by htop when settings are changed in the interface.
+# The parser is also very primitive, and not human-friendly.
+fields=0 48 39 2 46 49 1
+sort_key=47
+sort_direction=1
+hide_threads=0
+hide_kernel_threads=1
+hide_userland_threads=1
+shadow_other_users=0
+show_thread_names=0
+show_program_path=1
+highlight_base_name=1
+highlight_megabytes=1
+highlight_threads=1
+tree_view=1
+header_margin=0
+detailed_cpu_time=0
+cpu_count_from_zero=0
+show_cpu_usage=1
+show_cpu_frequency=0
+update_process_names=0
+account_guest_in_cpu_meter=0
+color_scheme=0
+enable_mouse=0
+delay=15
+left_meters=AllCPUs2
+left_meter_modes=1
+right_meters=Memory Swap
+right_meter_modes=1 1
diff --git a/home/.editrc b/home/.editrc
new file mode 100644
index 00000000..cf779a7d
--- /dev/null
+++ b/home/.editrc
@@ -0,0 +1 @@
+bind -v
diff --git a/home/.gdbinit b/home/.gdbinit
new file mode 100644
index 00000000..9422460c
--- /dev/null
+++ b/home/.gdbinit
@@ -0,0 +1 @@
+set disassembly-flavor intel
diff --git a/home/.hushlogin b/home/.hushlogin
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/home/.hushlogin
diff --git a/home/.inputrc b/home/.inputrc
new file mode 100644
index 00000000..b2cc9d61
--- /dev/null
+++ b/home/.inputrc
@@ -0,0 +1 @@
+set editing-mode vi
diff --git a/home/.lldbinit b/home/.lldbinit
new file mode 100644
index 00000000..73f3e676
--- /dev/null
+++ b/home/.lldbinit
@@ -0,0 +1 @@
+settings set target.x86-disassembly-flavor intel
diff --git a/home/.local/bin/aes b/home/.local/bin/aes
new file mode 100755
index 00000000..32b52637
--- /dev/null
+++ b/home/.local/bin/aes
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -eu
+
+enwiden() {
+	exec tr ' -~' ' ï¼-~'
+}
+[ $# -gt 0 ] && echo "$*" | enwiden || enwiden
diff --git a/home/.local/bin/clock b/home/.local/bin/clock
new file mode 100755
index 00000000..ef8cd6d8
--- /dev/null
+++ b/home/.local/bin/clock
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -eu
+
+tput civis
+sleep=$(( 60 - $(date +'%S' | sed 's/^0//') ))
+while :; do
+	if [ $(apm -a) -eq 1 ]; then
+		printf '%3s%%' "$(apm -l)"
+	else
+		test $(apm -b) -eq 2 && tput setaf 1 bold
+		printf '%3.3sm' "$(apm -m)"
+		tput sgr0
+	fi
+	printf ' %s\r' "$(date +'%a %H:%M')"
+	sleep $sleep
+	sleep=60
+done
diff --git a/home/.local/bin/def b/home/.local/bin/def
new file mode 100755
index 00000000..6a1681d3
--- /dev/null
+++ b/home/.local/bin/def
@@ -0,0 +1,47 @@
+#!/bin/sh
+set -eu
+
+macro=$1
+headers='
+assert.h
+complex.h
+ctype.h
+errno.h
+fenv.h
+float.h
+inttypes.h
+iso646.h
+limits.h
+locale.h
+math.h
+setjmp.h
+signal.h
+stdalign.h
+stdarg.h
+stdatomic.h
+stdbool.h
+stddef.h
+stdint.h
+stdio.h
+stdlib.h
+stdnoreturn.h
+string.h
+tgmath.h
+threads.h
+time.h
+uchar.h
+wchar.h
+wctype.h
+'
+
+for header in $headers; do
+	defined=$(
+		echo "$macro" \
+		| cc -E -x c -include "$header" - \
+		2> /dev/null \
+		| tail -n 1
+	)
+	[ $? -ne 0 -o "$defined" = "$macro" ] && continue
+	echo "#include <${header}>"
+	echo "$defined"
+done
diff --git a/home/.local/bin/deg b/home/.local/bin/deg
new file mode 100755
index 00000000..216029ed
--- /dev/null
+++ b/home/.local/bin/deg
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -eu
+cat <<EOF
+${1}°F = $(dc -e "1k $(echo "$1" | sed 's/^-/_/') 32-1.8/p")°C
+${1}°C = $(dc -e "1k $(echo "$1" | sed 's/^-/_/') 1.8*32+p")°F
+EOF
diff --git a/home/.local/bin/git-password b/home/.local/bin/git-password
new file mode 100755
index 00000000..41351e38
--- /dev/null
+++ b/home/.local/bin/git-password
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -eu
+
+url=$1
+echo "url=${url}" \
+	| git credential fill \
+	| sed -En 's/^password=(.*)/\1/p'
diff --git a/home/.local/bin/mdate b/home/.local/bin/mdate
new file mode 100755
index 00000000..daff50dc
--- /dev/null
+++ b/home/.local/bin/mdate
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec date +'.Dd %B %e, %Y'
diff --git a/home/.local/bin/nasd b/home/.local/bin/nasd
new file mode 100755
index 00000000..d64b2c3a
--- /dev/null
+++ b/home/.local/bin/nasd
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -eu
+
+dir=$(mktemp -d)
+echo 'bits 64' > "${dir}/input"
+cat >> "${dir}/input"
+nasm -o "${dir}/output" "${dir}/input" || true
+ndisasm -b 64 "${dir}/output" || true
+rm -r "$dir"
diff --git a/home/.local/bin/notify-send b/home/.local/bin/notify-send
new file mode 100755
index 00000000..5630440d
--- /dev/null
+++ b/home/.local/bin/notify-send
@@ -0,0 +1,9 @@
+#!/usr/bin/osascript
+
+on run argv
+	if count of argv is 2 then
+		display notification (item 2 of argv) with title (item 1 of argv)
+	else
+		display notification (item 1 of argv)
+	end if
+end run
diff --git a/home/.local/bin/np b/home/.local/bin/np
new file mode 100755
index 00000000..b0eb2326
--- /dev/null
+++ b/home/.local/bin/np
@@ -0,0 +1,7 @@
+#!/usr/bin/osascript
+
+tell application "Music"
+	tell current track
+		get "/me is listening to " & artist & " — " & name
+	end tell
+end tell
diff --git a/home/.local/bin/open b/home/.local/bin/open
new file mode 100755
index 00000000..cc13d0a6
--- /dev/null
+++ b/home/.local/bin/open
@@ -0,0 +1,18 @@
+#!/bin/sh
+set -eu
+
+if [ -n "${SSH_CLIENT:-}" ]; then
+	exec pbd -o "$@"
+fi
+
+case "$1" in
+	(*.gif|*.jpeg|*.jpg|*.png)
+		curl -LSs "$1" | imv -
+		;;
+	(https://youtu.be/*|https://www.youtube.com/watch*|https://twitch.tv/*)
+		exec mpv "$1" >/dev/null 2>&1
+		;;
+	(*)
+		exec firefox -new-tab "$1" >/dev/null 2>&1
+		;;
+esac
diff --git a/home/.local/bin/pbcopy b/home/.local/bin/pbcopy
new file mode 100755
index 00000000..a804f836
--- /dev/null
+++ b/home/.local/bin/pbcopy
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -eu
+
+if [ -n "${SSH_CLIENT:-}" ]; then
+	exec pbd -c
+elif [ -n "${DISPLAY:-}" ]; then
+	exec xsel -bi
+else
+	echo "${0}: don't know what to do" >&2
+	exit 1
+fi
diff --git a/home/.local/bin/pbpaste b/home/.local/bin/pbpaste
new file mode 100755
index 00000000..2924f01e
--- /dev/null
+++ b/home/.local/bin/pbpaste
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -eu
+
+if [ -n "${SSH_CLIENT:-}" ]; then
+	exec pbd -p
+elif [ -n "${DISPLAY:-}" ]; then
+	exec xsel -bo
+else
+	echo "${0}: don't know what to do" >&2
+	exit 1
+fi
diff --git a/home/.local/bin/versions b/home/.local/bin/versions
new file mode 100755
index 00000000..25e5ff72
--- /dev/null
+++ b/home/.local/bin/versions
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -u
+
+for repo in ~/src/git/*; do
+	version=$(git -C "${repo}" describe --dirty 2>/dev/null)
+	if [ $? -eq 0 ]; then
+		echo "${repo##*/}-${version#v}"
+	fi
+done | sort -nr -t '-' -k 3 | column -t -s '-'
diff --git a/home/.profile b/home/.profile
new file mode 100644
index 00000000..d719799b
--- /dev/null
+++ b/home/.profile
@@ -0,0 +1,23 @@
+_PATH=$PATH PATH=
+path() { [ -d "$1" ] && PATH="${PATH}${PATH:+:}${1}"; }
+for prefix in '' /usr/local /opt/local /usr ~/.local; do
+	path "${prefix}/sbin"
+	path "${prefix}/bin"
+done
+path /usr/X11R6/bin
+path /usr/games
+export MANPATH=:~/.local/share/man
+
+export EDITOR=vi
+type nvi >/dev/null && EDITOR=nvi
+export EXINIT='set ai ic sm sw=4 ts=4 para=BlBdPpIt sect=ShSs | map gg 1G'
+export PAGER=less
+export LESS=FRXix4
+export CLICOLOR=1
+export MANSECT=2:3:1:8:6:5:7:4:9
+export NETHACKOPTIONS='pickup_types:$!?+/=, color, DECgraphics'
+
+[ -e /usr/share/mk/sys.mk ] || export CFLAGS=-O
+[ -d /usr/home ] && cd
+
+export ENV=~/.shrc
diff --git a/home/.shrc b/home/.shrc
new file mode 100644
index 00000000..4b0e6c61
--- /dev/null
+++ b/home/.shrc
@@ -0,0 +1,63 @@
+set -o noclobber -o nounset -o vi
+
+CDPATH=:~
+
+alias vi=$EDITOR
+alias ls='LC_COLLATE=C ls -p'
+alias ll='ls -hl'
+alias ff='find . -type f -name'
+alias bc='bc -l'
+alias ag='ag --pager=$PAGER'
+alias gs='git status --short --branch || ls' gd='git diff'
+alias gsh='git show' gl='git log --graph --pretty=log'
+alias gco='git checkout' gb='git branch' gm='git merge' gst='git stash'
+alias ga='git add' gmv='git mv' grm='git rm'
+alias gc='git commit' gca='gc --amend' gt='git tag'
+alias gp='git push' gu='git pull' gf='git fetch' gr='git rebase'
+alias rand='openssl rand -base64 33'
+alias private='eval "$(gpg -d ~/.private)"'
+type doas >/dev/null && alias sudo=doas
+
+man() {
+	test $# -ne 1 && { command man "$@"; return $?; }
+	(IFS=:
+	for sect in $MANSECT; do
+		command man -w $sect "$1" >/dev/null 2>&1 && exec man $sect "$1"
+	done
+	exec man "$1")
+}
+
+cd() {
+	local path
+	if [ $# -eq 0 ]; then
+		command cd
+	elif [ "${1%%:*}" != "$1" ]; then
+		path=${1#*:}
+		[ -n "${path}" ] || path=${PWD#${HOME}/}
+		SSH_CD=$path ssh -o SendEnv=SSH_CD "${1%%:*}"
+	elif [ -e "$1" -a ! -d "$1" ]; then
+		command cd "${1%/*}" && $EDITOR "${1##*/}"
+	else
+		command cd "$@"
+	fi
+}
+if [ -n "${SSH_CD:-}" ]; then
+	cd "${SSH_CD}"
+	unset SSH_CD
+fi
+
+export LESS_TERMCAP_us=$(tput sitm)
+export LESS_TERMCAP_ue=$(tput ritm)
+
+hostname=$(hostname -s)
+rprompt() {
+	local pwd
+	pwd=${PWD#${HOME}}
+	[ "${pwd}" != "${PWD}" ] && pwd="~${pwd}"
+	[ "${TERM%-*}" = 'xterm' ] \
+		&& printf '\33]0;%s\a' "${SSH_CLIENT:+${hostname}:}${pwd##*/}" >&2
+	printf '%s' "${SSH_CLIENT:+${hostname}:}${pwd}"
+}
+PS1='
+$ '
+RPS1='${?#0} $(rprompt)'
diff --git a/home/.ssh/config b/home/.ssh/config
new file mode 100644
index 00000000..3fc6a8db
--- /dev/null
+++ b/home/.ssh/config
@@ -0,0 +1,18 @@
+IgnoreUnknown Include
+Include config_private
+
+HashKnownHosts yes
+
+SendEnv LANG LC_*
+
+Host monday beastie puffy toaster tux progynova
+	HostName %h.local
+	ForwardAgent yes
+	RemoteForward 7062 127.0.0.1:7062
+
+Host june july
+	HostName %h.nyc3.do.causal.agency
+	Port 2222
+
+Host git.causal.agency temp.causal.agency
+	Port 2222
diff --git a/home/.xsession b/home/.xsession
new file mode 100644
index 00000000..ca09445b
--- /dev/null
+++ b/home/.xsession
@@ -0,0 +1,12 @@
+. ~/.profile
+export LC_CTYPE=en_US.UTF-8
+
+xset r rate 175 m 5/4 0
+xmodmap ~/.config/X/modmap
+xrdb -load ~/.config/X/resources
+xsetroot -bitmap /usr/X11R6/include/X11/bitmaps/xsnow \
+	-bg rgb:14/13/0E -fg rgb:7A/49/55 
+
+sctd &
+xterm -name clock -geometry 14x1-0+0 -sl 0 -e clock &
+exec cwm -c ~/.config/cwm/cwmrc
diff --git a/install.sh b/install.sh
new file mode 100644
index 00000000..9e18c6bf
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+set -eu
+
+X=
+while getopts 'X' opt; do
+	case "$opt" in
+		(X) X=1;;
+		(?) exit 1;;
+	esac
+done
+
+packages='curl htop sl the_silver_searcher tree'
+
+FreeBSD() {
+	sudo pkg install ddate $packages
+}
+
+OpenBSD() {
+	doas pkg_add $packages
+	if test $X; then
+		doas pkg_add firefox go-fonts imv scrot sct w3m-- xcursor-dmz xsel
+	fi
+}
+
+Linux() {
+	sudo pacman -Sy --needed bc ctags gdb openssh vi $packages
+}
+
+installMacPorts() {
+	xcode-select --install
+	xcodebuild -license
+	dir=MacPorts-2.6.3
+	tar=${dir}.tar.bz2
+	curl -O "https://distfiles.macports.org/MacPorts/${tar}"
+	tar -x -f $tar
+	(cd $dir && ./configure)
+	make -C $dir
+	sudo make -C $dir install
+	rm -fr $tar $dir
+}
+
+Darwin() {
+	[ -d /opt/local ] || installMacPorts
+	sudo /opt/local/bin/port selfupdate
+	sudo /opt/local/bin/port -N install git mandoc nvi pkgconfig $packages
+	sudo mkdir -p /opt/local/etc/select/man
+	printf 'bin/man\nshare/man/man1/man.1\nshare/man/man1/man.1.gz\n' \
+		| sudo tee /opt/local/etc/select/man/base >/dev/null
+	printf '/usr/bin/man\n/usr/share/man/man1/man.1\n-\n' \
+		| sudo tee /opt/local/etc/select/man/system >/dev/null
+	sudo port select --set man system
+}
+
+$(uname)
diff --git a/link.sh b/link.sh
new file mode 100644
index 00000000..6763f2e0
--- /dev/null
+++ b/link.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+set -eu
+
+die() {
+	echo "$*"
+	exit 1
+}
+
+if [ $# -eq 1 ]; then
+	link=$1
+	file="${PWD}/home/${link#${HOME}/}"
+	[ ! -f "$file" ] || die "${file} exists"
+	mkdir -p "${file%/*}"
+	mv "$link" "$file"
+fi
+
+find home -type f | while read -r find; do
+	file="${PWD}/${find}"
+	link="${HOME}/${find#home/}"
+	mkdir -p "${link%/*}"
+	[ \( -f "$link" -a -L "$link" \) -o ! -f "$link" ] || die "${link} exists"
+	ln -fs "$file" "$link"
+done
diff --git a/port/caesar/.gitignore b/port/caesar/.gitignore
new file mode 100644
index 00000000..e2c3034b
--- /dev/null
+++ b/port/caesar/.gitignore
@@ -0,0 +1,2 @@
+caesar
+rot13
diff --git a/port/caesar/Makefile b/port/caesar/Makefile
new file mode 100644
index 00000000..01205b16
--- /dev/null
+++ b/port/caesar/Makefile
@@ -0,0 +1,19 @@
+PREFIX = ~/.local
+MANDIR = ${PREFIX}/share/man
+
+LDLIBS = -lm
+
+all: caesar rot13
+
+clean:
+	rm -f caesar rot13
+
+install: caesar rot13 caesar.6
+	install -d ${PREFIX}/bin ${MANDIR}/man6
+	install caesar rot13 ${PREFIX}/bin
+	install -m 644 caesar.6 ${MANDIR}/man6/caesar.6
+	install -m 644 caesar.6 ${MANDIR}/man6/rot13.6
+
+uninstall:
+	rm -f ${PREFIX}/bin/caesar ${PREFIX}/bin/rot13
+	rm -f ${MANDIR}/man6/caesar.6 ${MANDIR}/man6/rot13.6
diff --git a/port/caesar/caesar.6 b/port/caesar/caesar.6
new file mode 100644
index 00000000..4c4bbfb4
--- /dev/null
+++ b/port/caesar/caesar.6
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\"	The Regents of the University of California.  All rights reserved.
+.\"
+.\" 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.
+.\" 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+.\"
+.\"	@(#)caesar.6	8.2 (Berkeley) 11/16/93
+.\" $FreeBSD: releng/11.2/usr.bin/caesar/caesar.6 216239 2010-12-06 19:12:51Z uqs $
+.\"
+.Dd November 16, 1993
+.Dt CAESAR 6
+.Os
+.Sh NAME
+.Nm caesar , rot13
+.Nd decrypt caesar ciphers
+.Sh SYNOPSIS
+.Nm
+.Op Ar rotation
+.Nm rot13
+.Sh DESCRIPTION
+The
+.Nm
+utility attempts to decrypt caesar ciphers using English letter frequency
+statistics.
+.Nm Caesar
+reads from the standard input and writes to the standard output.
+.Pp
+The optional numerical argument
+.Ar rotation
+may be used to specify a specific rotation value.
+If invoked as
+.Nm rot13 ,
+a rotation value of 13 will be used.
+.Pp
+The frequency (from most common to least) of English letters is as follows:
+.Bd -ragged -offset indent
+ETAONRISHDLFCMUGPYWBVKXJQZ
+.Ed
+.Pp
+Their frequencies as a percentage are as follows:
+.Bd -ragged -offset indent
+E(13), T(10.5), A(8.1), O(7.9), N(7.1), R(6.8), I(6.3), S(6.1), H(5.2),
+D(3.8), L(3.4), F(2.9), C(2.7), M(2.5), U(2.4), G(2),
+P(1.9), Y(1.9),
+W(1.5), B(1.4), V(.9), K(.4), X(.15), J(.13), Q(.11), Z(.07).
+.Ed
+.Pp
+Rotated postings to
+.Tn USENET
+and some of the databases used by the
+.Xr fortune 6
+program are rotated by 13 characters.
diff --git a/port/caesar/caesar.c b/port/caesar/caesar.c
new file mode 100644
index 00000000..cd6cd579
--- /dev/null
+++ b/port/caesar/caesar.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Adams.
+ *
+ * Authors:
+ *	Stan King, John Eldridge, based on algorithm suggested by
+ *	Bob Morris
+ * 29-Sep-82
+ *
+ * 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+
+#if 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+	The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static const char sccsid[] = "@(#)caesar.c    8.1 (Berkeley) 5/31/93";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: releng/11.2/usr.bin/caesar/caesar.c 241846 2012-10-22 03:06:53Z eadler $");
+
+#include <errno.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#define	LINELENGTH	2048
+#define	ROTATE(ch, perm) \
+     isascii(ch) ? ( \
+	isupper(ch) ? ('A' + (ch - 'A' + perm) % 26) : \
+	    islower(ch) ? ('a' + (ch - 'a' + perm) % 26) : ch) : ch
+
+/*
+ * letter frequencies (taken from some unix(tm) documentation)
+ * (unix is a trademark of Bell Laboratories)
+ */
+static double stdf[26] = {
+	7.97, 1.35, 3.61, 4.78, 12.37, 2.01, 1.46, 4.49, 6.39, 0.04,
+	0.42, 3.81, 2.69, 5.92,  6.96, 2.91, 0.08, 6.63, 8.77, 9.68,
+	2.62, 0.81, 1.88, 0.23,  2.07, 0.06,
+};
+
+static void printit(char *);
+
+int
+main(int argc, char **argv)
+{
+	int ch, dot, i, nread, winnerdot = 0;
+	char *inbuf;
+	int obs[26], try, winner;
+
+	if (argc > 1)
+		printit(argv[1]);
+
+	if (!(inbuf = malloc((size_t)LINELENGTH))) {
+		(void)fprintf(stderr, "caesar: out of memory.\n");
+		exit(1);
+	}
+
+	/* adjust frequency table to weight low probs REAL low */
+	for (i = 0; i < 26; ++i)
+		stdf[i] = log(stdf[i]) + log(26.0 / 100.0);
+
+	/* zero out observation table */
+	bzero(obs, 26 * sizeof(int));
+
+	if ((nread = read(STDIN_FILENO, inbuf, (size_t)LINELENGTH)) < 0) {
+		(void)fprintf(stderr, "caesar: %s\n", strerror(errno));
+		exit(1);
+	}
+	for (i = nread; i--;) {
+		ch = (unsigned char) inbuf[i];
+		if (isascii(ch)) {
+			if (islower(ch))
+				++obs[ch - 'a'];
+			else if (isupper(ch))
+				++obs[ch - 'A'];
+		}
+	}
+
+	/*
+	 * now "dot" the freqs with the observed letter freqs
+	 * and keep track of best fit
+	 */
+	for (try = winner = 0; try < 26; ++try) { /* += 13) { */
+		dot = 0;
+		for (i = 0; i < 26; i++)
+			dot += obs[i] * stdf[(i + try) % 26];
+		/* initialize winning score */
+		if (try == 0)
+			winnerdot = dot;
+		if (dot > winnerdot) {
+			/* got a new winner! */
+			winner = try;
+			winnerdot = dot;
+		}
+	}
+
+	for (;;) {
+		for (i = 0; i < nread; ++i) {
+			ch = (unsigned char) inbuf[i];
+			putchar(ROTATE(ch, winner));
+		}
+		if (nread < LINELENGTH)
+			break;
+		if ((nread = read(STDIN_FILENO, inbuf, (size_t)LINELENGTH)) < 0) {
+			(void)fprintf(stderr, "caesar: %s\n", strerror(errno));
+			exit(1);
+		}
+	}
+	exit(0);
+}
+
+static void
+printit(char *arg)
+{
+	int ch, rot;
+
+	if ((rot = atoi(arg)) < 0) {
+		(void)fprintf(stderr, "caesar: bad rotation value.\n");
+		exit(1);
+	}
+	while ((ch = getchar()) != EOF)
+		putchar(ROTATE(ch, rot));
+	exit(0);
+}
diff --git a/port/caesar/rot13.sh b/port/caesar/rot13.sh
new file mode 100644
index 00000000..8ce4b94e
--- /dev/null
+++ b/port/caesar/rot13.sh
@@ -0,0 +1,33 @@
+#!/bin/sh -
+#
+# Copyright (c) 1992, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# 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.
+# 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+#
+#	@(#)rot13.sh	8.1 (Berkeley) 5/31/93
+# $FreeBSD: releng/11.2/usr.bin/caesar/rot13.sh 278616 2015-02-12 05:35:00Z cperciva $
+
+exec caesar 13 "$@"
diff --git a/port/cgram/.gitignore b/port/cgram/.gitignore
new file mode 100644
index 00000000..d4f2ec10
--- /dev/null
+++ b/port/cgram/.gitignore
@@ -0,0 +1 @@
+cgram
diff --git a/port/cgram/Makefile b/port/cgram/Makefile
new file mode 100644
index 00000000..02f11eec
--- /dev/null
+++ b/port/cgram/Makefile
@@ -0,0 +1,17 @@
+PREFIX = ~/.local
+MANDIR = ${PREFIX}/share/man
+
+LDLIBS = -lcurses
+
+cgram:
+
+clean:
+	rm -f cgram
+
+install: cgram cgram.6
+	install -d ${PREFIX}/bin ${MANDIR}/man6
+	install cgram ${PREFIX}/bin
+	install -m 644 cgram.6 ${MANDIR}/man6
+
+uninstall:
+	rm -f ${PREFIX}/bin/cgram ${MANDIR}/man6/cgram.6
diff --git a/port/cgram/cgram.6 b/port/cgram/cgram.6
new file mode 100644
index 00000000..9f315804
--- /dev/null
+++ b/port/cgram/cgram.6
@@ -0,0 +1,65 @@
+.\" $NetBSD: cgram.6,v 1.2 2013/08/04 07:55:09 wiz Exp $
+.\"
+.\" Copyright (c) 2004, 2013 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by David A. Holland.
+.\"
+.\" 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.
+.\"
+.Dd August 3, 2013
+.Dt CGRAM 6
+.Os
+.Sh NAME
+.Nm cgram
+.Nd solve Sunday-paper cryptograms
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+.Nm
+is a curses-based widget for solving Sunday-paper-type cryptograms
+based on substitution ciphers.
+A random cleartext is chosen using
+.Xr fortune 6
+and a random substitution key is generated.
+.Pp
+The ciphertext is displayed.
+Typing a letter changes the key so that the letter under the cursor
+maps to the newly typed letter, and updates the display accordingly.
+Use Emacs-type cursor commands to move around.
+Enter a tilde
+.Pq ~
+to quit.
+Press asterisk
+.Pq *
+to enter an easier mode where correct letters are displayed in
+boldface.
+.Sh SEE ALSO
+.Xr caesar 6
+.Sh HISTORY
+.Nm
+was written circa 2004.
+It was imported into
+.Nx
+in 2013 and first appeared in
+.Nx 7.0 .
diff --git a/port/cgram/cgram.c b/port/cgram/cgram.c
new file mode 100644
index 00000000..76ea55fb
--- /dev/null
+++ b/port/cgram/cgram.c
@@ -0,0 +1,344 @@
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David A. Holland.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <err.h>
+#include <assert.h>
+#include <curses.h>
+#include "pathnames.h"
+
+////////////////////////////////////////////////////////////
+
+static char *xstrdup(const char *s) {
+   char *ret;
+
+   ret = malloc(strlen(s) + 1);
+   if (ret == NULL) {
+      errx(1, "Out of memory");
+   }
+   strcpy(ret, s);
+   return ret;
+}
+
+////////////////////////////////////////////////////////////
+
+struct stringarray {
+   char **v;
+   int num;
+};
+
+static void stringarray_init(struct stringarray *a) {
+   a->v = NULL;
+   a->num = 0;
+}
+
+static void stringarray_cleanup(struct stringarray *a) {
+   free(a->v);
+}
+
+static void stringarray_add(struct stringarray *a, const char *s) {
+   a->v = realloc(a->v, (a->num + 1) * sizeof(a->v[0]));
+   if (a->v == NULL) {
+      errx(1, "Out of memory");
+   }
+   a->v[a->num] = xstrdup(s);
+   a->num++;
+}
+
+////////////////////////////////////////////////////////////
+
+static struct stringarray lines;
+static struct stringarray sollines;
+static bool hinting;
+static int scrolldown;
+static unsigned curx;
+static int cury;
+
+static void readquote(void) {
+   FILE *f = popen(_PATH_FORTUNE, "r");
+   if (!f) {
+      err(1, "%s", _PATH_FORTUNE);
+   }
+
+   char buf[128], buf2[8*sizeof(buf)];
+   while (fgets(buf, sizeof(buf), f)) {
+      char *s = strrchr(buf, '\n');
+      assert(s);
+      assert(strlen(s)==1);
+      *s = 0;
+
+      int i,j;
+      for (i=j=0; buf[i]; i++) {
+	 if (buf[i]=='\t') {
+	    buf2[j++] = ' ';
+	    while (j%8) buf2[j++] = ' ';
+	 }
+	 else if (buf[i]=='\b') {
+	    if (j>0) j--;
+	 }
+	 else {
+	    buf2[j++] = buf[i];
+	 }
+      }
+      buf2[j] = 0;
+
+      stringarray_add(&lines, buf2);
+      stringarray_add(&sollines, buf2);
+   }
+
+   pclose(f);
+}
+
+static void encode(void) {
+   int used[26];
+   for (int i=0; i<26; i++) used[i] = 0;
+
+   int key[26];
+   int keypos=0;
+   while (keypos < 26) {
+      int c = random()%26;
+      if (used[c]) continue;
+      key[keypos++] = c;
+      used[c] = 1;
+   }
+
+   for (int y=0; y<lines.num; y++) {
+      for (unsigned x=0; lines.v[y][x]; x++) {
+	 if (islower((unsigned char)lines.v[y][x])) {
+	    int q = lines.v[y][x]-'a';
+	    lines.v[y][x] = 'a'+key[q];
+	 }
+	 if (isupper((unsigned char)lines.v[y][x])) {
+	    int q = lines.v[y][x]-'A';
+	    lines.v[y][x] = 'A'+key[q];
+	 }
+      }
+   }
+}
+
+static int substitute(int ch) {
+   assert(cury>=0 && cury<lines.num);
+   if (curx >= strlen(lines.v[cury])) {
+      beep();
+      return -1;
+   }
+
+   int och = lines.v[cury][curx];
+   if (!isalpha((unsigned char)och)) {
+      beep();
+      return -1;
+   }
+
+   int loch = tolower((unsigned char)och);
+   int uoch = toupper((unsigned char)och);
+   int lch = tolower((unsigned char)ch);
+   int uch = toupper((unsigned char)ch);
+
+   for (int y=0; y<lines.num; y++) {
+      for (unsigned x=0; lines.v[y][x]; x++) {
+	 if (lines.v[y][x]==loch) {
+	    lines.v[y][x] = lch;
+	 }
+	 else if (lines.v[y][x]==uoch) {
+	    lines.v[y][x] = uch;
+	 }
+	 else if (lines.v[y][x]==lch) {
+	    lines.v[y][x] = loch;
+	 }
+	 else if (lines.v[y][x]==uch) {
+	    lines.v[y][x] = uoch;
+	 }
+      }
+   }
+   return 0;
+}
+
+////////////////////////////////////////////////////////////
+
+static void redraw(void) {
+   erase();
+   bool won = true;
+   for (int i=0; i<LINES-1; i++) {
+      move(i, 0);
+      int ln = i+scrolldown;
+      if (ln < lines.num) {
+	 for (unsigned j=0; lines.v[i][j]; j++) {
+	    int ch = lines.v[i][j];
+	    if (ch != sollines.v[i][j] && isalpha((unsigned char)ch)) {
+	       won = false;
+	    }
+	    bool bold=false;
+	    if (hinting && ch==sollines.v[i][j] &&
+		isalpha((unsigned char)ch)) {
+	       bold = true;
+	       attron(A_BOLD);
+	    }
+	    addch(lines.v[i][j]);
+	    if (bold) {
+	       attroff(A_BOLD);
+	    }
+	 }
+      }
+      clrtoeol();
+   }
+
+   move(LINES-1, 0);
+   if (won) {
+      addstr("*solved* ");
+   }
+   addstr("~ to quit, * to cheat, ^pnfb to move");
+
+   move(LINES-1, 0);
+
+   move(cury-scrolldown, curx);
+
+   refresh();
+}
+
+static void opencurses(void) {
+    initscr();
+    cbreak();
+    noecho();
+}
+
+static void closecurses(void) {
+   endwin();
+}
+
+////////////////////////////////////////////////////////////
+
+static void loop(void) {
+   bool done=false;
+   while (!done) {
+      redraw();
+      int ch = getch();
+      switch (ch) {
+       case 1: /* ^A */
+	curx=0;
+	break;
+       case 2: /* ^B */
+	if (curx > 0) {
+	   curx--;
+	}
+	else if (cury > 0) {
+	   cury--;
+	   curx = strlen(lines.v[cury]);
+	}
+	break;
+       case 5: /* ^E */
+	curx = strlen(lines.v[cury]);
+	break;
+       case 6: /* ^F */
+	if (curx < strlen(lines.v[cury])) {
+	   curx++;
+	}
+	else if (cury < lines.num - 1) {
+	   cury++;
+	   curx = 0;
+	}
+	break;
+       case 12: /* ^L */
+	clear();
+	break;
+       case 14: /* ^N */
+	if (cury < lines.num-1) {
+	   cury++;
+	}
+	if (curx > strlen(lines.v[cury])) {
+	   curx =  strlen(lines.v[cury]);
+	}
+	if (scrolldown < cury - (LINES-2)) {
+	   scrolldown = cury - (LINES-2);
+	}
+	break;
+       case 16: /* ^P */
+	if (cury > 0) {
+	   cury--;
+	}
+	if (curx > strlen(lines.v[cury])) {
+	   curx = strlen(lines.v[cury]);
+	}
+	if (scrolldown > cury) {
+	   scrolldown = cury;
+	}
+	break;
+       case '*':
+	hinting = !hinting;
+	break;
+       case '~':
+	done = true;
+	break;
+       default:
+	if (isalpha(ch)) {
+	   if (!substitute(ch)) {
+	      if (curx < strlen(lines.v[cury])) {
+		 curx++;
+	      }
+	      if (curx==strlen(lines.v[cury]) && cury < lines.num-1) {
+		 curx=0;
+		 cury++;
+	      }
+	   }
+	}
+	else if (curx < strlen(lines.v[cury]) && ch==lines.v[cury][curx]) {
+	   curx++;
+	   if (curx==strlen(lines.v[cury]) && cury < lines.num-1) {
+	      curx=0;
+	      cury++;
+	   }
+	}
+	else {
+	   beep();
+	}
+	break;
+      }
+   }
+}
+
+////////////////////////////////////////////////////////////
+
+int main(void) {
+   stringarray_init(&lines);
+   stringarray_init(&sollines);
+   srandom(time(NULL));
+   readquote();
+   encode();
+   opencurses();
+
+   loop();
+
+   closecurses();
+   stringarray_cleanup(&sollines);
+   stringarray_cleanup(&lines);
+   return 0;
+}
diff --git a/port/cgram/pathnames.h b/port/cgram/pathnames.h
new file mode 100644
index 00000000..40db1eed
--- /dev/null
+++ b/port/cgram/pathnames.h
@@ -0,0 +1,30 @@
+/*-
+ * Copyright (c) 2013 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by David A. Holland.
+ *
+ * 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.
+ */
+
+#define _PATH_FORTUNE "fortune"
diff --git a/port/ddate/.gitignore b/port/ddate/.gitignore
new file mode 100644
index 00000000..eaa8a5fd
--- /dev/null
+++ b/port/ddate/.gitignore
@@ -0,0 +1 @@
+ddate
diff --git a/port/ddate/Makefile b/port/ddate/Makefile
new file mode 100644
index 00000000..c1bc4553
--- /dev/null
+++ b/port/ddate/Makefile
@@ -0,0 +1,15 @@
+PREFIX ?= ~/.local
+MANDIR ?= ${PREFIX}/share/man
+
+ddate:
+
+clean:
+	rm -f ddate
+
+install: ddate ddate.1
+	install -d ${PREFIX}/bin ${MANDIR}/man1
+	install ddate ${PREFIX}/bin
+	install -m 644 ddate.1 ${MANDIR}/man1
+
+uninstall:
+	rm -f ${PREFIX}/bin/ddate ${MANDIR}/man1/ddate.1
diff --git a/port/ddate/ddate.1 b/port/ddate/ddate.1
new file mode 100644
index 00000000..c340578f
--- /dev/null
+++ b/port/ddate/ddate.1
@@ -0,0 +1,117 @@
+.\" All Rites Reversed.  This file is in the PUBLIC DOMAIN.
+.\" Kallisti.
+.TH DDATE 1 "Bureaucracy 3161" "ddate" "Emperor Norton User Command"
+.SH NAME
+ddate \- convert Gregorian dates to Discordian dates
+.SH SYNOPSIS
+.B ddate
+.RI [ \fB+\fPformat]
+.RI [ date ]
+.SH DESCRIPTION
+.B ddate
+prints the date in Discordian date format.
+.PP
+If called with no arguments,
+.B ddate
+will get the current system date, convert this to the Discordian
+date format and print this on the standard output. Alternatively, a
+Gregorian date may be specified on the command line, in the form of a numerical
+day, month and year.
+.PP
+If a format string is specified, the Discordian date will be printed in
+a format specified by the string. This mechanism works similarly to the
+format string mechanism of
+.B date(1),
+only almost completely differently. The fields are:
+.IP %A
+Full name of the day of the week (i.e., Sweetmorn)
+.IP %a
+Abbreviated name of the day of the week (i.e., SM)
+.IP %B
+Full name of the season (i.e., Chaos)
+.IP %b
+Abbreviated name of the season (i.e., Chs)
+.IP %d
+Cardinal number of day in season (i.e., 23)
+.IP %e
+Ordinal number of day in season (i.e., 23rd)
+.IP %H
+Name of current Holyday, if any
+.IP %N
+Magic code to prevent rest of format from being printed unless today is
+a Holyday.
+.IP %n
+Newline
+.IP %t
+Tab
+.IP %X
+Number of days remaining until X-Day. (Not valid if the SubGenius options
+are not compiled in.)
+.IP %Y
+The year of our Lady Discord (i.e., 3182)
+.IP %{
+.IP %}
+Used to enclose the part of the string which is to be replaced with the
+words "St. Tib's Day" if the current day is St. Tib's Day.
+.IP %\.
+Try it and see.
+.bp
+.SH EXAMPLES
+.nf
+% ddate
+.br
+Sweetmorn, Bureaucracy 42, 3161 YOLD
+.PP
+% ddate +'Today is %{%A, the %e of %B%}, %Y. %N%nCelebrate %H'
+.br
+Today is Sweetmorn, the 42nd of Bureaucracy, 3161.
+.PP
+% ddate +"It's %{%A, the %e of %B%}, %Y. %N%nCelebrate %H" 26 9 1995
+.br
+It's Prickle-Prickle, the 50th of Bureaucracy, 3161.
+.br
+Celebrate Bureflux
+.PP
+% ddate +"Today's %{%A, the %e of %B%}, %Y. %N%nCelebrate %H" 29 2 1996
+.br
+Today's St. Tib's Day, 3162.
+.br
+
+.SH BUGS
+
+.B ddate(1)
+will produce undefined behavior if asked to produce the date for St. Tib's
+day and its format string does not contain the St. Tib's Day delimiters
+%{ and %}.
+
+.SH NOTE
+
+After `X-Day' passed without incident, the Church of the SubGenius
+declared that it had got the year upside down - X-Day is actually in 8661 AD
+rather than 1998 AD.  Thus, the True X-Day is Cfn 40, 9827.
+
+.SH AUTHOR
+.nh
+Original program by Druel the Chaotic aka Jeremy Johnson (mpython@gnu.ai.mit.edu)
+.br
+Major rewrite by Lee H:. O:. Smith, KYTP, aka Andrew Bulhak (acb@dev.null.org)
+.br
+Gregorian B.C.E. dates fixed by Chaplain Nyan the Wiser, aka Dan Dart (ntw@dandart.co.uk)
+.br
+Five tons of flax.
+
+.SH DISTRIBUTION POLICY
+
+Public domain. All rites reversed.
+
+.SH SEE ALSO
+
+date(1),
+.br
+http://www.subgenius.com/
+.br
+Malaclypse the Younger,
+.I "Principia Discordia, Or How I Found Goddess And What I Did To Her When I Found Her"
+
+.SH AVAILABILITY
+The ddate command is available from https://github.com/bo0ts/ddate.
diff --git a/port/ddate/ddate.c b/port/ddate/ddate.c
new file mode 100644
index 00000000..c0a6bf37
--- /dev/null
+++ b/port/ddate/ddate.c
@@ -0,0 +1,399 @@
+/* $ DVCS ID: $jer|,523/lhos,KYTP!41023161\b"?" <<= DO NOT DELETE! */
+
+/* ddate.c .. converts boring normal dates to fun Discordian Date -><-
+   written  the 65th day of The Aftermath in the Year of Our Lady of 
+   Discord 3157 by Druel the Chaotic aka Jeremy Johnson aka
+   mpython@gnu.ai.mit.edu  
+      28 Sever St Apt #3
+      Worcester MA 01609
+
+   and I'm not responsible if this program messes anything up (except your 
+   mind, I'm responsible for that)
+
+   (k) YOLD 3161 and all time before and after.
+   Reprint, reuse, and recycle what you wish.
+   This program is in the public domain.  Distribute freely.  Or not.
+
+   Majorly hacked, extended and bogotified/debogotified on 
+   Sweetmorn, Bureaucracy 42, 3161 YOLD, by Lee H:. O:. Smith, KYTP, 
+   aka Andrew Bulhak, aka acb@dev.null.org
+
+   Slightly hackled and crackled by a sweet firey stove on
+   Boomtime, the 53rd day of Bureaucracy in the YOLD 3179,
+   by Chaplain Nyan the Wiser, aka Dan Dart, aka ntw@dandart.co.uk
+
+   and I'm not responsible if this program messes anything up (except your 
+   mind, I'm responsible for that) (and that goes for me as well --lhos)
+
+   Version history:
+   Bureflux 3161:      First release of enhanced ddate with format strings
+   59 Bcy, 3161:       PRAISE_BOB and KILL_BOB options split, other minor
+                       changes.
+   53 Bcy, 3179:       Fixed gregorian date conversions less than YOLD 1167
+
+   1999-02-22 Arkadiusz Miskiewicz <misiek@pld.ORG.PL>
+   - added Native Language Support
+
+   2000-03-17 Burt Holzman <holzman+ddate@gmail.com>
+   - added range checks for dates
+
+   2014-06-07 William Woodruff <william@tuffbizz.com>
+   - removed gettext dependent locale code
+
+   15th of Confusion, 3180:
+   - call out adherents of the wrong fruit
+
+   FIVE TONS OF FLAX
+*/
+
+/* configuration options  VVVVV   READ THIS!!! */
+
+/* If you wish ddate(1) to print the date in the same format as Druel's 
+ * original ddate when called in immediate mode, define OLD_IMMEDIATE_FMT 
+ */
+
+#define OLD_IMMEDIATE_FMT
+
+/* If you wish to use the US format for aneristic dates (m-d-y), as opposed to
+ * the Commonwealth format, define US_FORMAT.
+ */
+
+/* #define US_FORMAT */
+
+/* If you are ideologically, theologically or otherwise opposed to the 
+ * Church of the SubGenius and do not wish your copy of ddate(1) to contain
+ * code for counting down to X-Day, undefine KILL_BOB */
+
+#define KILL_BOB 13013
+
+/* If you wish ddate(1) to contain SubGenius slogans, define PRAISE_BOB */
+
+/*#define PRAISE_BOB 13013*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+
+// work around includes and defines from formerly c.h
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+#endif
+
+/* &a[0] degrades to a pointer: a different type from an array */
+# define __must_be_array(a) \
+	BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(__typeof__(a), __typeof__(&a[0])))
+
+#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
+
+/* work around hacks for standalone package */
+#define PACKAGE "ddate"
+#define PACKAGE_STRING "Stand Alone"
+
+#ifndef __GNUC__
+#define inline /* foo */
+#endif
+
+#ifdef KILL_BOB
+int xday_countdown(int yday, int year);
+#endif
+
+
+/* string constants */
+
+char *day_long[5] = { 
+    "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"
+};
+
+char *day_short[5] = {"SM","BT","PD","PP","SO"};
+
+char *season_long[5] = { 
+    "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"
+};
+
+char *season_short[5] = {"Chs", "Dsc", "Cfn", "Bcy", "Afm"};
+
+char *holyday[5][2] = { 
+    { "Mungday", "Chaoflux" },
+    { "Mojoday", "Discoflux" },
+    { "Syaday",  "Confuflux" },
+    { "Zaraday", "Bureflux" },
+    { "Maladay", "Afflux" }
+};
+
+struct disc_time {
+    int season; /* 0-4 */
+    int day; /* 0-72 */
+    int yday; /* 0-365 */
+    int year; /* 3066- */
+};
+
+char *excl[] = {
+    "Hail Eris!", "All Hail Discordia!", "Kallisti!", "Fnord.", "Or not.",
+    "Wibble.", "Pzat!", "P'tang!", "Frink!",
+#ifdef PRAISE_BOB
+    "Slack!", "Praise \"Bob\"!", "Or kill me.",
+#endif /* PRAISE_BOB */
+    /* randomness, from the Net and other places. Feel free to add (after
+       checking with the relevant authorities, of course). */
+    "Grudnuk demand sustenance!", "Keep the Lasagna flying!",
+    "You are what you see.",
+    "Or is it?", "This statement is false.",
+    "Lies and slander, sire!", "Hee hee hee!",
+#if defined(linux) || defined (__linux__) || defined (__linux)
+    "Hail Eris, Hack Linux!",
+#elif defined(__APPLE__)
+    "This Fruit is not the True Fruit of Discord.",
+#endif
+    ""
+};
+
+char default_fmt[] = "%{%A, %B %d%}, %Y YOLD";
+char *default_immediate_fmt=
+#ifdef OLD_IMMEDIATE_FMT
+"Today is %{%A, the %e day of %B%} in the YOLD %Y%N%nCelebrate %H"
+#else
+default_fmt
+#endif
+;
+
+#define DY(y) (y+1166)
+
+static inline char *ending(int i) {
+	return i/10==1?"th":(i%10==1?"st":(i%10==2?"nd":(i%10==3?"rd":"th")));
+}
+
+static inline int leapp(int i) {
+	return (!(DY(i)%4))&&((DY(i)%100)||(!(DY(i)%400)));
+}
+
+/* select a random string */
+static inline char *sel(char **strings, int num) {
+	return(strings[random()%num]);
+}
+
+void print(struct disc_time,char **); /* old */
+void format(char *buf, const char* fmt, struct disc_time dt);
+/* read a fortune file */
+int load_fortunes(char *fn, char *delim, char** result);
+
+struct disc_time convert(int,int);
+struct disc_time makeday(int,int,int);
+
+int
+main (int argc, char *argv[]) {
+    time_t t;
+    struct tm *eris;
+    int bob,raw;
+    struct disc_time hastur;
+    char schwa[23*17], *fnord=0;
+    int pi;
+    char *progname, *p;
+
+    progname = argv[0];
+    if ((p = strrchr(progname, '/')) != NULL)
+	progname = p+1;
+
+    srandom(time(NULL));
+    /* do args here */
+    for(pi=1; pi<argc; pi++) {
+	switch(argv[pi][0]) {
+	case '+': fnord=argv[pi]+1; break;
+	case '-': 
+	    switch(argv[pi][1]) {
+	    case 'V':
+		printf(("%s (%s)\n"), progname, PACKAGE_STRING);
+	    default: goto usage;
+	    }
+	default: goto thud;
+	}
+    }
+
+  thud:
+    if (argc-pi==3){ 
+	int moe=atoi(argv[pi]), larry=atoi(argv[pi+1]), curly=atoi(argv[pi+2]);
+	hastur=makeday(
+#ifdef US_FORMAT
+	    moe,larry,
+#else
+	    larry,moe,
+#endif
+	    curly);
+	if (hastur.season == -1) {
+		printf("Invalid date -- out of range\n");
+		return -1;
+	}
+	fnord=fnord?fnord:default_fmt;
+    } else if (argc!=pi) { 
+      usage:
+	fprintf(stderr,("usage: %s [+format] [day month year]\n"), argv[0]);
+	exit(1);
+    } else {
+	t= time(NULL);
+	eris=localtime(&t);
+	bob=eris->tm_yday; /* days since Jan 1. */
+	raw=eris->tm_year; /* years since 1980 */
+	hastur=convert(bob,raw);
+	fnord=fnord?fnord:default_immediate_fmt;
+    }
+    format(schwa, fnord, hastur);
+    printf("%s\n", schwa);
+   
+    return 0;
+}
+
+void format(char *buf, const char* fmt, struct disc_time dt)
+{
+    int tib_start=-1, tib_end=0;
+    int i, fmtlen=strlen(fmt);
+    char *bufptr=buf;
+
+/*    fprintf(stderr, "format(%p, \"%s\", dt)\n", buf, fmt);*/
+
+    /* first, find extents of St. Tib's Day area, if defined */
+    for(i=0; i<fmtlen; i++) {
+	if(fmt[i]=='%') {
+	    switch(fmt[i+1]) {
+	    case 'A':
+	    case 'a':
+	    case 'd':
+	    case 'e':
+		if(tib_start>0)	    tib_end=i+1;
+		else		    tib_start=i;
+		break;
+	    case '{': tib_start=i; break;
+	    case '}': tib_end=i+1; break;
+	    }
+	}
+    }
+
+    /* now do the formatting */
+    buf[0]=0;
+
+    for(i=0; i<fmtlen; i++) {
+	if((i==tib_start) && (dt.day==-1)) {
+	    /* handle St. Tib's Day */
+	    strcpy(bufptr, ("St. Tib's Day"));
+	    bufptr += strlen(bufptr);
+	    i=tib_end;
+	} else {
+	    if(fmt[i]=='%') {
+		char *wibble=0, snarf[23];
+		switch(fmt[++i]) {
+		case 'A': wibble=day_long[dt.yday%5]; break;
+		case 'a': wibble=day_short[dt.yday%5]; break;
+		case 'B': wibble=season_long[dt.season]; break;
+		case 'b': wibble=season_short[dt.season]; break;
+		case 'd': sprintf(snarf, "%d", dt.day+1); wibble=snarf; break;
+		case 'e': sprintf(snarf, "%d%s", dt.day+1, ending(dt.day+1)); 
+		    wibble=snarf; break;
+		case 'H': if(dt.day==4||dt.day==49)
+		    wibble=holyday[dt.season][dt.day==49]; break;
+		case 'N': if(dt.day!=4&&dt.day!=49) goto eschaton; break;
+		case 'n': *(bufptr++)='\n'; break;
+		case 't': *(bufptr++)='\t'; break;
+
+		case 'Y': sprintf(snarf, "%d", dt.year); wibble=snarf; break;
+		case '.': wibble=sel(excl, ARRAY_SIZE(excl));
+		    break;
+#ifdef KILL_BOB
+		case 'X': sprintf(snarf, "%d", 
+				  xday_countdown(dt.yday, dt.year));
+				  wibble = snarf; break;
+#endif /* KILL_BOB */
+		}
+		if(wibble) {
+/*		    fprintf(stderr, "wibble = (%s)\n", wibble);*/
+		    strcpy(bufptr, wibble); bufptr+=strlen(wibble);
+		}
+	    } else {
+		*(bufptr++) = fmt[i];
+	    }
+	}
+    }
+  eschaton:
+    *(bufptr)=0;
+}
+
+struct disc_time makeday(int imonth,int iday,int iyear) /*i for input */
+{ 
+    struct disc_time funkychickens;
+    
+    int cal[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
+    int dayspast=0;
+
+    memset(&funkychickens,0,sizeof(funkychickens));
+    /* basic range checks */
+    if (imonth < 1 || imonth > 12 || iyear == 0) {
+	    funkychickens.season = -1;
+	    return funkychickens;
+    }
+    if (iday < 1 || iday > cal[imonth-1]) {
+	    if (!(imonth == 2 && iday == 29 && iyear%4 == 0 &&
+		  (iyear%100 != 0 || iyear%400 == 0))) {
+		    funkychickens.season = -1;
+		    return funkychickens;
+	    }
+    }
+    
+    imonth--;
+    /*  note: gregorian year 0 doesn't exist so
+     *  add one if user specifies a year less than 0 */
+    funkychickens.year= iyear+1166 + ((0 > iyear)?1:0);
+    while(imonth>0) { dayspast+=cal[--imonth]; }
+    funkychickens.day=dayspast+iday-1;
+    funkychickens.season=0;
+    if((funkychickens.year%4)==2) {
+	if (funkychickens.day==59 && iday==29)  funkychickens.day=-1;
+    }
+    funkychickens.yday=funkychickens.day;
+/*               note: EQUAL SIGN...hopefully that fixes it */
+    while(funkychickens.day>=73) {
+	funkychickens.season++;
+	funkychickens.day-=73;
+    }
+    return funkychickens;
+}
+
+struct disc_time convert(int nday, int nyear)
+{  struct disc_time funkychickens;
+   
+   funkychickens.year = nyear+3066;
+   funkychickens.day=nday;
+   funkychickens.season=0;
+   if ((funkychickens.year%4)==2)
+     {if (funkychickens.day==59)
+	funkychickens.day=-1;
+     else if (funkychickens.day >59)
+       funkychickens.day-=1;
+    }
+   funkychickens.yday=funkychickens.day;
+   while (funkychickens.day>=73)
+     { funkychickens.season++;
+       funkychickens.day-=73;
+     }
+   return funkychickens;
+  
+ }
+
+#ifdef KILL_BOB
+
+/* Code for counting down to X-Day, X-Day being Cfn 40, 3164 
+ *
+ * After `X-Day' passed without incident, the CoSG declared that it had 
+ * got the year upside down --- X-Day is actually in 8661 AD rather than 
+ * 1998 AD.
+ *
+ * Thus, the True X-Day is Cfn 40, 9827.
+ *
+ */
+
+int xday_countdown(int yday, int year) {
+    int r=(185-yday)+(((yday<59)&&(leapp(year)))?1:0);
+    while(year<9827) r+=(leapp(++year)?366:365);
+    while(year>9827) r-=(leapp(year--)?366:365);
+    return r;
+}
+
+#endif
diff --git a/port/file2c/.gitignore b/port/file2c/.gitignore
new file mode 100644
index 00000000..aafb358f
--- /dev/null
+++ b/port/file2c/.gitignore
@@ -0,0 +1 @@
+file2c
diff --git a/port/file2c/Makefile b/port/file2c/Makefile
new file mode 100644
index 00000000..09f6b5d0
--- /dev/null
+++ b/port/file2c/Makefile
@@ -0,0 +1,15 @@
+PREFIX = ~/.local
+MANDIR = ${PREFIX}/share/man
+
+file2c:
+
+clean:
+	rm -f file2c
+
+install: file2c file2c.1
+	install -d ${PREFIX}/bin ${MANDIR}/man1
+	install file2c ${PREFIX}/bin
+	install -m 644 file2c.1 ${MANDIR}/man1
+
+uninstall:
+	rm -f ${PREFIX}/bin/file2c ${MANDIR}/man1/file2c.1
diff --git a/port/file2c/file2c.1 b/port/file2c/file2c.1
new file mode 100644
index 00000000..fe1fe5e7
--- /dev/null
+++ b/port/file2c/file2c.1
@@ -0,0 +1,75 @@
+.\"----------------------------------------------------------------------------
+.\" "THE BEER-WARE LICENSE" (Revision 42):
+.\" <phk@FreeBSD.org> wrote this file.  As long as you retain this notice, you
+.\" can do whatever you want with this file. If we meet some day, and you think
+.\" this stuff is worth it, you can buy me a beer in return.  Poul-Henning Kamp
+.\" ---------------------------------------------------------------------------
+.\"
+.\" $FreeBSD: releng/11.2/usr.bin/file2c/file2c.1 173197 2007-10-30 17:49:00Z ru $
+.\"
+.Dd March 22, 2007
+.Dt FILE2C 1
+.Os
+.Sh NAME
+.Nm file2c
+.Nd convert file to c-source
+.Sh SYNOPSIS
+.Nm
+.Op Fl sx
+.Op Fl n Ar count
+.Op Ar prefix Op Ar suffix
+.Sh DESCRIPTION
+The
+.Nm
+utility reads a file from stdin and writes it to stdout, converting each
+byte to its decimal or hexadecimal representation on the fly.
+The byte values are separated by a comma.
+This also means that the last byte value is not followed by a comma.
+By default the byte values are printed in decimal, but when the
+.Fl x
+option is given, the values will be printed in hexadecimal.
+When
+.Fl s
+option is given, each line is printed with a leading tab and each comma is
+followed by a space except for the last one on the line.
+.Pp
+If more than 70 characters are printed on the same line, that line is
+ended and the output continues on the next line.
+With the
+.Fl n
+option this can be made to happen after the specified number of
+byte values have been printed.
+The length of the line will not be considered anymore.
+To have all the byte values printed on the same line, give the
+.Fl n
+option a negative number.
+.Pp
+A prefix and suffix strings can be printed before and after the byte values
+(resp.)
+If a suffix is to be printed, a prefix must also be specified.
+The first non-option word is the prefix, which may optionally be followed
+by a word that is to be used as the suffix.
+.Pp
+This program is typically used to embed binary files into C source files.
+The prefix is used to define an array type and the suffix is used to end
+the C statement.
+The
+.Fl n , s
+and
+.Fl x
+options are useful when the binary data represents a bitmap and the output
+needs to remain readable and/or editable.
+Fonts, for example, are a good example of this.
+.Sh EXAMPLES
+The command:
+.Bd -literal -offset indent
+date | file2c 'const char date[] = {' ',0};'
+.Ed
+.Pp
+will produce:
+.Bd -literal -offset indent
+const char date[] = {
+83,97,116,32,74,97,110,32,50,56,32,49,54,58,50,56,58,48,53,
+32,80,83,84,32,49,57,57,53,10
+,0};
+.Ed
diff --git a/port/file2c/file2c.c b/port/file2c/file2c.c
new file mode 100644
index 00000000..cff7f602
--- /dev/null
+++ b/port/file2c/file2c.c
@@ -0,0 +1,92 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+
+#include <sys/cdefs.h>
+//__FBSDID("$FreeBSD: releng/11.2/usr.bin/file2c/file2c.c 200462 2009-12-13 03:14:06Z delphij $");
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "usage: %s [-sx] [-n count] [prefix [suffix]]\n",
+	    "file2c");
+	exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+	int c, count, linepos, maxcount, pretty, radix;
+
+	maxcount = 0;
+	pretty = 0;
+	radix = 10;
+	while ((c = getopt(argc, argv, "n:sx")) != -1) {
+		switch (c) {
+		case 'n':	/* Max. number of bytes per line. */
+			maxcount = strtol(optarg, NULL, 10);
+			break;
+		case 's':	/* Be more style(9) comliant. */
+			pretty = 1;
+			break;
+		case 'x':	/* Print hexadecimal numbers. */
+			radix = 16;
+			break;
+		case '?':
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	if (argc > 0)
+		printf("%s\n", argv[0]);
+	count = linepos = 0;
+	while((c = getchar()) != EOF) {
+		if (count) {
+			putchar(',');
+			linepos++;
+		}
+		if ((maxcount == 0 && linepos > 70) ||
+		    (maxcount > 0 && count >= maxcount)) {
+			putchar('\n');
+			count = linepos = 0;
+		}
+		if (pretty) {
+			if (count) {
+				putchar(' ');
+				linepos++;
+			} else {
+				putchar('\t');
+				linepos += 8;
+			}
+		}
+		switch (radix) {
+		case 10:
+			linepos += printf("%d", c);
+			break;
+		case 16:
+			linepos += printf("0x%02x", c);
+			break;
+		default:
+			abort();
+		}
+		count++;
+	}
+	putchar('\n');
+	if (argc > 1)
+		printf("%s\n", argv[1]);
+	return (0);
+}
diff --git a/port/wcwidth/.gitignore b/port/wcwidth/.gitignore
new file mode 100644
index 00000000..132e8098
--- /dev/null
+++ b/port/wcwidth/.gitignore
@@ -0,0 +1,3 @@
+*.o
+libwcwidth.dylib
+wcfix
diff --git a/port/wcwidth/COPYRIGHT b/port/wcwidth/COPYRIGHT
new file mode 100644
index 00000000..e6472371
--- /dev/null
+++ b/port/wcwidth/COPYRIGHT
@@ -0,0 +1,190 @@
+musl as a whole is licensed under the following standard MIT license:
+
+----------------------------------------------------------------------
+Copyright © 2005-2020 Rich Felker, et al.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+----------------------------------------------------------------------
+
+Authors/contributors include:
+
+A. Wilcox
+Ada Worcester
+Alex Dowad
+Alex Suykov
+Alexander Monakov
+Andre McCurdy
+Andrew Kelley
+Anthony G. Basile
+Aric Belsito
+Arvid Picciani
+Bartosz Brachaczek
+Benjamin Peterson
+Bobby Bingham
+Boris Brezillon
+Brent Cook
+Chris Spiegel
+Clément Vasseur
+Daniel Micay
+Daniel Sabogal
+Daurnimator
+David Carlier
+David Edelsohn
+Denys Vlasenko
+Dmitry Ivanov
+Dmitry V. Levin
+Drew DeVault
+Emil Renner Berthing
+Fangrui Song
+Felix Fietkau
+Felix Janda
+Gianluca Anzolin
+Hauke Mehrtens
+He X
+Hiltjo Posthuma
+Isaac Dunham
+Jaydeep Patil
+Jens Gustedt
+Jeremy Huntwork
+Jo-Philipp Wich
+Joakim Sindholt
+John Spencer
+Julien Ramseier
+Justin Cormack
+Kaarle Ritvanen
+Khem Raj
+Kylie McClain
+Leah Neukirchen
+Luca Barbato
+Luka Perkov
+M Farkas-Dyck (Strake)
+Mahesh Bodapati
+Markus Wichmann
+Masanori Ogino
+Michael Clark
+Michael Forney
+Mikhail Kremnyov
+Natanael Copa
+Nicholas J. Kain
+orc
+Pascal Cuoq
+Patrick Oppenlander
+Petr Hosek
+Petr Skocik
+Pierre Carrier
+Reini Urban
+Rich Felker
+Richard Pennington
+Ryan Fairfax
+Samuel Holland
+Segev Finer
+Shiz
+sin
+Solar Designer
+Stefan Kristiansson
+Stefan O'Rear
+Szabolcs Nagy
+Timo Teräs
+Trutz Behn
+Valentin Ochs
+Will Dietz
+William Haddon
+William Pitcock
+
+Portions of this software are derived from third-party works licensed
+under terms compatible with the above MIT license:
+
+The TRE regular expression implementation (src/regex/reg* and
+src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
+under a 2-clause BSD license (license text in the source files). The
+included version has been heavily modified by Rich Felker in 2012, in
+the interests of size, simplicity, and namespace cleanliness.
+
+Much of the math library code (src/math/* and src/complex/*) is
+Copyright © 1993,2004 Sun Microsystems or
+Copyright © 2003-2011 David Schultz or
+Copyright © 2003-2009 Steven G. Kargl or
+Copyright © 2003-2009 Bruce D. Evans or
+Copyright © 2008 Stephen L. Moshier or
+Copyright © 2017-2018 Arm Limited
+and labelled as such in comments in the individual source files. All
+have been licensed under extremely permissive terms.
+
+The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008
+The Android Open Source Project and is licensed under a two-clause BSD
+license. It was taken from Bionic libc, used on Android.
+
+The implementation of DES for crypt (src/crypt/crypt_des.c) is
+Copyright © 1994 David Burren. It is licensed under a BSD license.
+
+The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
+originally written by Solar Designer and placed into the public
+domain. The code also comes with a fallback permissive license for use
+in jurisdictions that may not recognize the public domain.
+
+The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
+Valentin Ochs and is licensed under an MIT-style license.
+
+The x86_64 port was written by Nicholas J. Kain and is licensed under
+the standard MIT terms.
+
+The mips and microblaze ports were originally written by Richard
+Pennington for use in the ellcc project. The original code was adapted
+by Rich Felker for build system and code conventions during upstream
+integration. It is licensed under the standard MIT terms.
+
+The mips64 port was contributed by Imagination Technologies and is
+licensed under the standard MIT terms.
+
+The powerpc port was also originally written by Richard Pennington,
+and later supplemented and integrated by John Spencer. It is licensed
+under the standard MIT terms.
+
+All other files which have no copyright comments are original works
+produced specifically for use as part of this library, written either
+by Rich Felker, the main author of the library, or by one or more
+contibutors listed above. Details on authorship of individual files
+can be found in the git version control history of the project. The
+omission of copyright and license comments in each file is in the
+interest of source tree size.
+
+In addition, permission is hereby granted for all public header files
+(include/* and arch/*/bits/*) and crt files intended to be linked into
+applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
+the copyright notice and permission notice otherwise required by the
+license, and to use these files without any requirement of
+attribution. These files include substantial contributions from:
+
+Bobby Bingham
+John Spencer
+Nicholas J. Kain
+Rich Felker
+Richard Pennington
+Stefan Kristiansson
+Szabolcs Nagy
+
+all of whom have explicitly granted such permission.
+
+This file previously contained text expressing a belief that most of
+the files covered by the above exception were sufficiently trivial not
+to be subject to copyright, resulting in confusion over whether it
+negated the permissions granted in the license. In the spirit of
+permissive licensing, and of not having licensing issues being an
+obstacle to adoption, that text has been removed.
diff --git a/port/wcwidth/Makefile b/port/wcwidth/Makefile
new file mode 100644
index 00000000..50faa653
--- /dev/null
+++ b/port/wcwidth/Makefile
@@ -0,0 +1,27 @@
+PREFIX ?= ~/.local
+
+OBJS = wcwidth.o wcswidth.o
+
+all: libwcwidth.dylib wcfix
+
+libwcwidth.dylib: ${OBJS}
+	${CC} -dynamiclib ${LDFLAGS} ${OBJS} -o $@
+
+wcwidth.o: nonspacing.h wide.h
+
+.SUFFIXES: .in
+
+.in:
+	sed 's|%%PREFIX%%|${PREFIX}|g' $< > $@
+	chmod a+x $@
+
+clean:
+	rm -f libwcwidth.dylib wcfix ${OBJS}
+
+install: libwcwidth.dylib wcfix
+	install -d ${PREFIX}/lib ${PREFIX}/bin
+	install -m 644 libwcwidth.dylib ${PREFIX}/lib
+	install wcfix ${PREFIX}/bin
+
+uninstall:
+	rm -f ${PREFIX}/lib/libwcwidth.dylib ${PREFIX}/bin/wcfix
diff --git a/port/wcwidth/nonspacing.h b/port/wcwidth/nonspacing.h
new file mode 100644
index 00000000..5d05a3d1
--- /dev/null
+++ b/port/wcwidth/nonspacing.h
@@ -0,0 +1,89 @@
+16,16,16,18,19,20,21,22,23,24,25,26,27,28,29,30,31,16,16,32,16,16,16,33,34,35,
+36,37,38,39,16,16,40,16,16,16,16,16,16,16,16,16,16,16,41,42,16,16,43,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,44,16,45,46,47,48,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,49,16,16,50,
+51,16,52,53,54,16,16,16,16,16,16,55,16,16,56,16,57,58,59,60,61,62,63,64,65,66,
+67,68,16,69,70,71,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,72,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,73,74,16,16,16,75,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,76,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,77,78,16,16,16,16,16,16,16,79,16,16,16,16,16,80,81,82,16,16,16,16,16,83,
+84,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,248,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,254,255,255,255,255,191,182,0,0,0,0,0,0,0,63,0,255,23,0,0,0,0,0,248,255,
+255,0,0,1,0,0,0,0,0,0,0,0,0,0,0,192,191,159,61,0,0,0,128,2,0,0,0,255,255,255,
+7,0,0,0,0,0,0,0,0,0,0,192,255,1,0,0,0,0,0,0,248,15,32,0,0,192,251,239,62,0,0,
+0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,255,255,255,255,
+255,7,0,0,0,0,0,0,20,254,33,254,0,12,0,0,0,2,0,0,0,0,0,0,16,30,32,0,0,12,0,0,
+64,6,0,0,0,0,0,0,16,134,57,2,0,0,0,35,0,6,0,0,0,0,0,0,16,190,33,0,0,12,0,0,
+252,2,0,0,0,0,0,0,144,30,32,64,0,12,0,0,0,4,0,0,0,0,0,0,0,1,32,0,0,0,0,0,0,17,
+0,0,0,0,0,0,192,193,61,96,0,12,0,0,0,2,0,0,0,0,0,0,144,64,48,0,0,12,0,0,0,3,0,
+0,0,0,0,0,24,30,32,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,4,92,0,0,0,0,0,0,0,0,0,0,0,
+242,7,128,127,0,0,0,0,0,0,0,0,0,0,0,0,242,31,0,63,0,0,0,0,0,0,0,0,0,3,0,0,160,
+2,0,0,0,0,0,0,254,127,223,224,255,254,255,255,255,31,64,0,0,0,0,0,0,0,0,0,0,0,
+0,224,253,102,0,0,0,195,1,0,30,0,100,32,0,32,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,
+0,0,28,0,0,0,12,0,0,0,12,0,0,0,0,0,0,0,176,63,64,254,15,32,0,0,0,0,0,120,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,135,1,4,14,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,9,0,0,0,0,0,0,64,127,
+229,31,248,159,0,0,0,0,0,0,255,127,0,0,0,0,0,0,0,0,15,0,0,0,0,0,208,23,4,0,0,
+0,0,248,15,0,3,0,0,0,60,59,0,0,0,0,0,0,64,163,3,0,0,0,0,0,0,240,207,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,255,253,33,16,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,
+251,0,248,0,0,0,124,0,0,0,0,0,0,223,255,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,
+255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,0,0,0,0,
+0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,128,247,63,0,0,0,192,0,0,0,0,0,0,0,0,0,0,3,0,68,8,0,0,96,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,255,255,3,128,0,0,0,0,192,63,0,0,128,255,3,0,
+0,0,0,0,7,0,0,0,0,0,200,51,0,0,0,0,32,0,0,0,0,0,0,0,0,126,102,0,8,16,0,0,0,0,
+0,16,0,0,0,0,0,0,157,193,2,0,0,0,0,48,64,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,33,0,0,0,0,0,64,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,0,0,255,255,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,110,240,0,0,0,0,0,135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,
+0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,192,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,255,
+127,0,0,0,0,0,0,128,3,0,0,0,0,0,120,38,0,32,0,0,0,0,0,0,7,0,0,0,128,239,31,0,
+0,0,0,0,0,0,8,0,3,0,0,0,0,0,192,127,0,30,0,0,0,0,0,0,0,0,0,0,0,128,211,64,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,248,7,0,0,3,0,0,0,0,0,0,24,1,0,0,0,192,
+31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,92,0,0,64,0,0,0,0,0,
+0,0,0,0,0,248,133,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,60,176,1,0,0,48,0,0,0,
+0,0,0,0,0,0,0,248,167,1,0,0,0,0,0,0,0,0,0,0,0,0,40,191,0,0,0,0,0,0,0,0,0,0,0,
+0,224,188,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+128,255,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,12,1,0,0,0,254,7,0,0,0,0,248,121,128,0,
+126,14,0,0,0,0,0,252,127,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,191,0,0,0,
+0,0,0,0,0,0,0,252,255,255,252,109,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,126,180,191,0,
+0,0,0,0,0,0,0,0,163,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,
+0,0,0,0,0,0,0,255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,0,0,0,0,0,127,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,
+0,128,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,15,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,3,248,255,231,15,0,0,0,60,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,255,255,255,255,255,255,127,248,255,255,255,255,255,31,32,0,16,0,0,248,
+254,255,0,0,0,0,0,0,0,0,0,
+0,127,255,255,249,219,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,240,7,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,
diff --git a/port/wcwidth/wcfix.in b/port/wcwidth/wcfix.in
new file mode 100644
index 00000000..832c83d6
--- /dev/null
+++ b/port/wcwidth/wcfix.in
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -eu
+
+export DYLD_FORCE_FLAT_NAMESPACE=1
+export DYLD_INSERT_LIBRARIES=%%PREFIX%%/lib/libwcwidth.dylib
+
+exec "$@"
diff --git a/port/wcwidth/wcswidth.c b/port/wcwidth/wcswidth.c
new file mode 100644
index 00000000..5c8a5a4d
--- /dev/null
+++ b/port/wcwidth/wcswidth.c
@@ -0,0 +1,8 @@
+#include <wchar.h>
+
+int wcswidth(const wchar_t *wcs, size_t n)
+{
+	int l=0, k=0;
+	for (; n-- && *wcs && (k = wcwidth(*wcs)) >= 0; l+=k, wcs++);
+	return (k < 0) ? k : l;
+}
diff --git a/port/wcwidth/wcwidth.c b/port/wcwidth/wcwidth.c
new file mode 100644
index 00000000..36256a53
--- /dev/null
+++ b/port/wcwidth/wcwidth.c
@@ -0,0 +1,29 @@
+#include <wchar.h>
+
+static const unsigned char table[] = {
+#include "nonspacing.h"
+};
+
+static const unsigned char wtable[] = {
+#include "wide.h"
+};
+
+int wcwidth(wchar_t wc)
+{
+	if (wc < 0xffU)
+		return (wc+1 & 0x7f) >= 0x21 ? 1 : wc ? -1 : 0;
+	if ((wc & 0xfffeffffU) < 0xfffe) {
+		if ((table[table[wc>>8]*32+((wc&255)>>3)]>>(wc&7))&1)
+			return 0;
+		if ((wtable[wtable[wc>>8]*32+((wc&255)>>3)]>>(wc&7))&1)
+			return 2;
+		return 1;
+	}
+	if ((wc & 0xfffe) == 0xfffe)
+		return -1;
+	if (wc-0x20000U < 0x20000)
+		return 2;
+	if (wc == 0xe0001 || wc-0xe0020U < 0x5f || wc-0xe0100U < 0xef)
+		return 0;
+	return 1;
+}
diff --git a/port/wcwidth/wide.h b/port/wcwidth/wide.h
new file mode 100644
index 00000000..e403c9a5
--- /dev/null
+++ b/port/wcwidth/wide.h
@@ -0,0 +1,65 @@
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,18,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,19,16,20,21,22,16,16,16,23,16,16,24,25,26,27,28,17,
+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,29,
+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+17,17,17,17,17,17,17,17,30,16,16,16,16,31,16,16,17,17,17,17,17,17,17,17,17,17,
+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+17,17,17,17,17,17,17,32,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,16,16,16,33,
+34,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,35,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,
+17,17,17,17,17,17,36,17,17,37,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,38,39,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,40,41,42,43,44,45,46,47,16,48,49,16,16,16,16,
+16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,6,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,30,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,0,48,0,0,0,0,0,0,255,15,0,0,0,0,128,0,0,8,
+0,2,12,0,96,48,64,16,0,0,4,44,36,32,12,0,0,0,1,0,0,0,80,184,0,0,0,0,0,0,0,224,
+0,0,0,1,128,0,0,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,251,255,255,255,255,255,255,255,
+255,255,255,15,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,63,0,0,0,255,15,255,255,255,255,
+255,255,255,127,254,255,255,255,255,255,255,255,255,255,127,254,255,255,255,
+255,255,255,255,255,255,255,255,255,224,255,255,255,255,255,254,255,255,255,
+255,255,255,255,255,255,255,127,255,255,255,255,255,7,255,255,255,255,15,0,
+255,255,255,255,255,127,255,255,255,255,255,0,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0,
+0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,31,255,255,255,255,255,255,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,
+255,255,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,15,0,0,0,0,0,0,0,0,0,0,0,0,0,255,3,0,0,255,255,255,255,247,255,127,15,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,254,255,255,255,255,255,255,255,255,255,255,
+255,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,7,0,255,255,255,127,0,0,0,0,0,
+0,7,0,240,0,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+15,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,64,254,7,0,0,0,0,0,0,0,0,0,0,0,0,7,0,255,255,255,
+255,255,15,255,1,3,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,
+1,224,191,255,255,255,255,255,255,255,255,223,255,255,15,0,255,255,255,255,
+255,135,15,0,255,255,17,255,255,255,255,255,255,255,255,127,253,255,255,255,
+255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+159,255,255,255,255,255,255,255,63,0,120,255,255,255,0,0,4,0,0,96,0,16,0,0,0,
+0,0,0,0,0,0,0,248,255,255,255,255,255,255,255,255,255,255,0,0,0,0,0,0,255,255,
+255,255,255,255,255,255,63,16,39,0,0,24,240,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,255,15,0,
+0,0,224,255,255,255,255,255,255,255,255,255,255,255,255,123,252,255,255,255,
+255,231,199,255,255,255,231,255,255,255,255,255,255,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,15,7,7,0,63,0,0,0,0,0,0,0,0,0,0,0,0,0,
diff --git a/prune.sh b/prune.sh
new file mode 100644
index 00000000..fabe865f
--- /dev/null
+++ b/prune.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+set -eu
+
+find -L ~/.config ~/.local -type l -lname "${PWD}/*" | while read -r link; do
+	echo "$link"
+	rm "$link"
+done
diff --git a/tests/filters/dump.lua b/tests/filters/dump.lua
deleted file mode 100644
index 1f15c931..00000000
--- a/tests/filters/dump.lua
+++ /dev/null
@@ -1,17 +0,0 @@
-function filter_open(...)
-	buffer = ""
-	for i = 1, select("#", ...) do
-		buffer = buffer .. select(i, ...) .. " "
-	end
-end
-
-function filter_close()
-	html(buffer)
-	return 0
-end
-
-function filter_write(str)
-	buffer = buffer .. string.upper(str)
-end
-
-
diff --git a/txt/.notemap b/txt/.notemap
new file mode 100644
index 00000000..acfe44ab
--- /dev/null
+++ b/txt/.notemap
@@ -0,0 +1,3 @@
+5347bbff-b124-432a-a67e-5d90fa34d0d4 books.txt
+9efa92ef-a8c0-4fa6-8a2a-13315992162b music.txt
+2d3c58f2-a193-4ff5-b79f-fd430f80eb64 shows.txt
diff --git a/txt/books.txt b/txt/books.txt
new file mode 100644
index 00000000..44b3ad66
--- /dev/null
+++ b/txt/books.txt
@@ -0,0 +1,129 @@
+[ 2021 ]
+
+ 12. ★★☆ Margaret Atwood, The Year of the Flood
+ 11. ★★☆ Charlie Jane Anders, All the Birds in the Sky
+ 10. ★☆☆ Margaret Atwood, The Penelopiad
+  9. ★★★ Alix E. Harrow, The Once and Future Witches
+  8. ★★☆ Mary Robinette Kowal, The Relentless Moon
+  7. ★☆☆ Connie Willis, Bellwether
+  6. ★★☆ Carmen Maria Machado, Her Body and Other Parties
+  5. ★★☆ N. K. Jemisin, The City We Became
+  4. ★★★ Martha Wells, Network Effect
+  3. ★★☆ Nnedi Okorafor, Binti
+  2. ★★☆ Kai Cheng Thom, I Hope We Choose Love
+  1. ★★☆ Tade Thompson, The Rosewater Redemption
+
+[ 2020 ]
+
+ 19. ★★★ N. K. Jemisin, The Awakened Kingdom
+ 18. ★★☆ N. K. Jemisin, The Kingdom of Gods
+ 17. ★★☆ N. K. Jemisin, The Broken Kingdoms
+ 16. ★★☆ Ann Leckie, Ancillary Justice
+ 15. ★★☆ Madeline Miller, The Song of Achilles
+ 14. ★★☆ N. K. Jemisin, The Hundred Thousand Kingdoms
+ 13. ★★☆ Annalee Newitz, Autonomous
+ 12. ★☆☆ Tade Thompson, The Rosewater Insurrection
+ 11. ★★☆ Alix E. Harrow, The Ten Thousand Doors of January
+ 10. ★★☆ N. K. Jemisin, The Stone Sky
+  9. ★★★ Kai Cheng Thom, Fierce Femmes and Notorious Liars
+  8. ★☆☆ Amal El-Mohtar & Max Gladstone, This Is How You Lose the Time War
+  7. ★★★ N. K. Jemisin, The Obelisk Gate
+  6. ★★★ Becky Chambers, To Be Taught, If Fortunate
+  5. ★★★ Annalee Newitz, The Future of Another Timeline
+  4. ★★☆ Rivers Solomon, The Deep
+  3. ★★☆ ed. Hope Nicholson, Love Beyond Body, Space & Time
+  2. ★★☆ Tade Thompson, Rosewater
+  1. ★★★ Meg Elison, The Book of Flora
+
+[ 2019 ]
+
+ 42. ★★★ Meg Elison, The Book of Etta
+ 41. ★★☆ Martha Wells, Exit Strategy
+ 40. ★★☆ Martha Wells, Artificial Condition
+ 39. ★★☆ N. K. Jemisin, The Fifth Season
+ 38. ★★☆ Martha Wells, Rogue Protocol
+ 37. ★★☆ Yoon Ha Lee, Ninefox Gambit
+ 36. ★★★ Rebecca Makkai, The Great Believers
+ 35. ★★☆ Meg Elison, The Book of the Unnamed Midwife
+ 34. ★★☆ Martha Wells, All Systems Red
+ 33. ★★☆ Nnedi Okorafor, The Book of Phoenix
+ 32. ★★☆ JY Yang, The Red Threads of Fortune
+ 31. ★★☆ JY Yang, The Black Tides of Heaven
+ 30. ★☆☆ Rebecca Roanhorse, Trail of Lightning
+ 29. ★☆☆ Jo Walton, The Just City
+ 28. ★★★ Arkady Martine, A Memory Called Empire
+ 27. ★★☆ Mary Robinette Kowal, The Fated Sky
+ 26. ★★★ Becky Chambers, Record of a Spaceborn Few
+ 25. ★★☆ Mary Robinette Kowal, The Calculating Stars
+ 24. ★★☆ Octavia E. Butler, Imago
+ 23. ★★☆ Octavia E. Butler, Kindred
+ 22. ★★☆ Octavia E. Butler, Adulthood Rites
+ 21. ★★★ Octavia E. Butler, Wild Seed
+ 20. ★★☆ Octavia E. Butler, Parable of the Talents
+ 19. ★★☆ Jeff VanderMeer, Acceptance
+ 18. ★★★ Becky Chambers, A Closed and Common Orbit
+ 17. ★★☆ Octavia E. Butler, Dawn
+ 16. ★★☆ Jeff VanderMeer, Authority
+ 15. ★★☆ Octavia E. Butler, Parable of the Sower
+ 14. ★★☆ C. A. Higgins, Lightless
+ 13. ★☆☆ Alfred Bester, The Demolished Man
+ 12. ★★★ Karin Tidbeck, Amatka
+ 11. ★☆☆ Catherynne M. Valente, Space Opera
+ 10. ★★☆ Rivers Solomon, An Unkindness of Ghosts
+  9. ★★★ Becky Chambers, The Long Way to a Small Angry Planet
+  8. ★★☆ Emily St. John Mandel, Station Eleven
+  7. ★★★ Douglas Adams, Dirk Gently's Holistic Detective Agency
+  6. ★★★ Octavia E. Butler, Fledgling
+  5. ★★★ Jeff VanderMeer, Annihilation
+  4. ★★☆ Alfred Bester, The Stars My Destination
+  3. ★☆☆ Samuel R. Delany, The Einstein Intersection
+  2. ★★★ Octavia E. Butler, Mind of My Mind
+  1. ★☆☆ Robert A. Heinlein, Waldo & Magic, Inc.
+
+[ 2018 ]
+
+ 25. ★★★ Douglas Adams, The Long Dark Tea-Time of the Soul
+ 24. ★★☆ Khaled Hosseini, A Thousand Splendid Suns
+ 23. ★★☆ Nathan Altice, I Am Error
+ 22. ★★★ Ruth Ozeki, A Tale for the Time Being
+ 21. ★☆☆ Arthur C. Clarke, Earthlight
+ 20. ★★★ Terry Pratchett & Neil Gaiman, Good Omens
+ 19. ★☆☆ Robert A. Heinlein, Starship Troopers
+ 18. ★★☆ Liu Cixin, The Three-Body Problem
+ 17. ★★☆ Robert A. Heinlein, Revolt in 2100
+ 16. ★★☆ ed. Robert A. Heinlein, Tomorrow, the Stars
+ 15. ★★☆ Robert A. Heinlein, Assignment in Eternity
+ 14. ★☆☆ Robert A. Heinlein, The Rolling Stones
+ 13. ★★☆ Robert A. Heinlein, Starman Jones
+ 12. ★☆☆ Robert A. Heinlein, Space Cadet
+ 11. ★☆☆ Robert A. Heinlein, Farmer in the Sky
+ 10. ★★☆ Robert A. Heinlein, Between Planets
+  9. ★★☆ Robert A. Heinlein, Red Planet
+  8. ★☆☆ Robert A. Heinlein, Rocket Ship Galileo
+  7. ★☆☆ Robert A. Heinlein, Sixth Column
+  6. ★☆☆ Robert A. Heinlein, Beyond This Horizon
+  5. ★★☆ Robert A. Heinlein, Orphans of the Sky
+  4. ★★☆ Tracy Kidder, The Soul of a New Machine
+  3. ★★★ James Alan Gardner, Ascending
+  2. ★★★ Anne Frank, The Diary of a Young Girl
+  1. ★★★ Harper Lee, Go Set a Watchman
+
+[ 2017 ]
+
+  1. ★★★ James Alan Gardner, Expendable
+
+[ ... ]
+
+ • ★★★ Harper Lee, To Kill a Mockingbird
+ • ★★★ Douglas Adams, The Hitchhiker's Guide to the Galaxy
+ • ★★★ Douglas Adams, The Restaurant at the End of the Universe
+ • ★★☆ Douglas Adams, Life, the Universe and Everything
+ • ★★★ Douglas Adams, So Long, and Thanks for All the Fish
+ • ★★☆ Douglas Adams, Mostly Harmless
+ • ★☆☆ Eoin Colfer, And Another Thing...
+ • ★★★ Margaret Atwood, The Handmaid's Tale
+ • ★★☆ Kazuo Ishiguro, Never Let Me Go
+ • ★★★ Philip Pullman, The Goldan Compass
+ • ★★★ Philip Pullman, The Subtle Knife
+ • ★★★ Philip Pullman, The Amber Spyglass
+ • ★★★ William Goldman, The Princess Bride
diff --git a/txt/music.txt b/txt/music.txt
new file mode 100644
index 00000000..cd3705c4
--- /dev/null
+++ b/txt/music.txt
@@ -0,0 +1,285 @@
+Feist — I Feel It All
+<https://youtu.be/g-1Gb2rxzlk>
+
+The Blow — "Come On Petunia"
+<https://youtu.be/MO1HSfzK1Ns>
+
+Black Country, New Road — Sunglasses
+<https://youtu.be/UAZhzi9cpkc>
+
+Mitski, Xiu Xiu — Between the Breaths
+<https://youtu.be/HnhTkFl5Imw>
+
+Black Dresses — CREEP U
+<https://youtu.be/w9RSZmltcVI>
+
+BACKXWASH — DONT COME TO THE WOODS
+<https://youtu.be/7ZcJsWyGbOw>
+
+William Bonney — See Ya Later
+<https://youtu.be/-uCUlvUlr9s>
+
+Four Tet — Hands
+<https://youtu.be/ojZoQbRt1tc>
+
+Buffy Sainte-Marie — Darling Don't Cry
+
+LINGUA IGNOTA — DO YOU DOUBT ME TRAITOR
+<https://youtu.be/M1ZweG__q-w>
+
+Lizzo — Truth Hurts
+<https://youtu.be/P00HMxdsVZI>
+
+Hobo Johnson and The Lovemakers — Tiny Desk Concert
+<https://youtu.be/A8a2EosJIbM>
+
+Poppy — Concrete
+<https://youtu.be/WwoGhpYdebQ>
+
+Kim Petras — Do Me
+<https://youtu.be/LShK0Yhd964>
+
+Kim Petras — Heart to Break
+<https://youtu.be/5CPeHQHAQyo>
+
+Anomie — Avorter n'est pas tuer
+<https://youtu.be/W1iGXRDeZf4>
+
+Zhaoze — Birds Contending
+<https://zhaoze.bandcamp.com/album/birds-contending>
+
+Colin Stetson — Reborn
+<https://youtu.be/MVnSFj6XQZY>
+
+Holly Herndon — Frontier
+<https://youtu.be/rvNqNgHAEys>
+
+Bleachers — Tiny Desk Concert
+<https://youtu.be/QCtkkX2f18M>
+
+Girlpool — Tiny Desk Concert
+<https://youtu.be/VNM8Tg9pvDU>
+
+Daughters — You Won't Get What You Want
+<https://daughters.bandcamp.com/album/you-wont-get-what-you-want>
+
+La Dispute — FULTON STREET I
+<https://ladispute.bandcamp.com/track/fulton-street-i>
+
+KASHIWA Daisuke — Stella
+<https://youtu.be/ei7cdynwRMA>
+
+Jeff Wayne — The Eve of the War
+<https://youtu.be/6YwFvmnbj3E>
+
+Julia Holter — I Shall Love 2
+<https://youtu.be/k5uwPaCvbhA>
+
+Chromatics — Running Up That Hill
+<https://youtu.be/Mgv88ZLi6LY>
+
+Low — Double Negative
+<https://lowtheband.bandcamp.com/album/double-negative>
+
+Rival Consoles — Helios
+<https://youtu.be/T8n-XC_2a-k>
+
+Tiffany — I Think We're Alone Now
+<https://youtu.be/w6Q3mHyzn78>
+
+Pulp — Common People
+<https://youtu.be/yuTMWgOduFM>
+
+XTC — Making Plans for Nigel
+<https://youtu.be/gZjZBCZWxpg>
+
+New Order — Temptation
+<https://youtu.be/xxDv_RTdLQo>
+
+Street Sects — In for a World of Hurt
+<https://streetsects.bandcamp.com/track/in-for-a-world-of-hurt>
+
+New Order — Temptation
+<https://youtu.be/xxDv_RTdLQo>
+
+Blondie — Heart of Glass
+<https://youtu.be/fWPhhlKHM80>
+
+Suuns — Watch You, Watch Me
+<https://suuns.bandcamp.com/track/watch-you-watch-me>
+
+Neckbeard Deathcamp — White Nationalism is for Basement Dwelling Losers
+<https://neckbearddeathcamp.bandcamp.com/album/white-nationalism-is-for-basement-dwelling-losers>
+
+rook — shed blood
+<https://rooksfeather.bandcamp.com/album/shed-blood>
+
+SOPHIE — OIL OF EVERY PEARL'S UN-INSIDES
+<http://smarturl.it/SOPHIEALBUM>
+
+Rosetta — Utopioid
+<https://theanaesthete.bandcamp.com/album/utopioid>
+
+Desire — Under Your Spell
+<https://youtu.be/9K7rmxjk5RQ>
+
+Broken Social Scene — Anthems for a Seventeen-Year Old Girl
+<https://youtu.be/DDqNL0js0iU>
+
+Shinsei Kamattechan — Yuugure no tori
+<https://youtu.be/sUW4dDWiz-A>
+
+Petite Meller — The Flute
+<https://youtu.be/BLwgeV7dXOI>
+
+King Gizzard and the Lizard Wizard — Flying Microtonal Banana
+<https://youtu.be/D0BsgJxw208>
+
+rook&nomie — DAYDREAM
+<https://youtu.be/00TdaTffFeY>
+
+Spiritualized — Ladies and Gentlemen We Are Floating in Space
+<https://youtu.be/p47V3w4m1yg>
+
+Street Sects — End Position
+<https://streetsects.bandcamp.com/album/end-position-2>
+
+Converge — The Dusk in Us
+<https://convergecult.bandcamp.com/album/the-dusk-in-us>
+
+St. Vincent — MASSEDUCTION
+
+Godspeed You! Black Emperor — Undoing a Luciferian Towers
+<https://godspeedyoublackemperor.bandcamp.com/track/undoing-a-luciferian-towers>
+
+Florist — Tiny Desk Concert
+<https://youtu.be/WbyyxIZ02Zs>
+
+CHVRCHES — Tiny Desk Concert
+<https://youtu.be/haunJARHPm4>
+
+Aurora — Tiny Desk Concert
+<https://youtu.be/evBgLWQwAFA>
+
+Joy Division — Atmosphere
+<https://youtu.be/1EdUjlawLJM>
+
+Underworld — Born Slippy
+<https://youtu.be/iTFrCbQGyvM>
+
+Converge — I Can Tell You About Pain
+<https://convergecult.bandcamp.com/album/i-can-tell-you-about-pain>
+
+CocoRosie — Lost Girls
+<https://youtu.be/aRa-SlftLQo>
+
+FAUVE — Blizzard
+<https://youtu.be/HMpmedi_pH4>
+
+FAUVE — Nuits Fauves
+<https://youtu.be/cwaAppsy5yo>
+
+Sarin — House of Leaves
+<https://sarin.bandcamp.com/track/house-of-leaves-split-w-guiltfeeder>
+
+Chromatics — Shadow
+<https://youtu.be/IGUboLZx3Tk>
+
+Arcade Fire — Creature Comfort
+<https://youtu.be/xzwicesJQ7E>
+
+Arcade Fire — Everything Now
+<https://youtu.be/zC30BYR3CUk>
+
+Ed Schrader's Music Beat — Sermon
+
+Jessica Moss — Pools of Light
+
+Death Grips — Steroids (Crouching Tiger Hidden Gabber Megamix)
+<https://youtu.be/JUTKTk60aGk>
+
+Saltland — A Common Truth
+
+Colin Stetson — All This I Do for Glory
+<https://colinstetson.bandcamp.com/album/all-this-i-do-for-glory>
+
+Xiu Xiu — Forget
+<https://youtu.be/ywRzfwA75pY>
+
+Arca — Arca
+
+Joni Void — Dissociation (Kyla's Song)
+<http://cstrecords.com/cst125/>
+
+Do Make Say Think — Bound and Boundless
+<http://cstrecords.com/cst120/>
+
+The Body Lovers / The Body Haters
+
+Unwound — Leaves Turn Inside You
+
+Xiu Xiu — Fabulous Muscles
+
+Xiu Xiu — A Promise
+
+Saltland — Light of Mercy
+<http://cstrecords.com/saltland-releases-new-single-light-of-mercy/>
+
+Jessica Moss — Glaciers I (Pt I)
+<http://cstrecords.com/cst124/>
+
+BNNY RBBT — Big World
+<http://www.bnnyrbbt.fans>
+
+Woman is the Earth — Depths
+<https://womanistheearth.bandcamp.com/album/depths>
+
+Saltland — I Only Wish This For You
+<http://cstrecords.com/cst123/>
+
+Sun Kil Moon — Benji
+<https://youtu.be/UtndQzCUEY4>
+
+Neil Cicierega — Mouth Moods
+<http://www.neilcic.com/mouthmoods/>
+
+Those Who Walk Away — "First Degraded Rhythm" + "First Partially Recollected Conversation"
+<http://cstrecords.com/cst122/>
+
+Dan Smith — Some Tunes
+<https://thedancemyth.bandcamp.com/album/some-tunes>
+
+Avec le soleil sortant de sa bouche — Pas pire pop, I Love You So Much
+
+Arcade Fire — I Give You Power
+<https://youtu.be/f6jma9VQEls>
+
+Xiu Xiu — Jenny GoGo
+<https://youtu.be/WMT6MsA3ut8>
+
+Kero Kero Bonito — Fish Bowl
+<https://youtu.be/FY-CjOJCjJE>
+
+Avec le soleil sortant de sa bouche — Alizé et Margaret D. Midi moins le quart. Sur la plage, un palmier ensanglanté
+<http://cstrecords.com/cst121/>
+
+G.L.O.S.S. — Trans Day of Revenge
+<https://girlslivingoutsidesocietysshit.bandcamp.com/releases>
+
+Joy Division — Love Will Tear Us Apart
+<https://youtu.be/zuuObGsB0No>
+
+Xiu Xiu — Honeysuckle
+<https://youtu.be/hYKGR8Er4vM>
+
+Xiu Xiu — Ceremony
+<https://youtu.be/95ms8A2XJY0>
+
+Xiu Xiu — I Luv the Valley Oh
+<https://youtu.be/dztURk0_DOg>
+
+Porter Robinson & Madeon — Shelter
+<https://youtu.be/fzQ6gRAEoy0>
+
+Julien Baker — Tiny Desk Concert
+<https://youtu.be/tADWPTqR_4A>
diff --git a/txt/plan.7 b/txt/plan.7
new file mode 100644
index 00000000..f861d395
--- /dev/null
+++ b/txt/plan.7
@@ -0,0 +1,26 @@
+.Dd March 10, 2021
+.Dt PLAN 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm plan
+.Nd possible future projects
+.
+.Sh DESCRIPTION
+.
+.Ss feed reader for IMAP
+.Bl -bullet -compact
+.It
+why use a separate reader
+when you already have a mail client?
+.It
+feeds go into IMAP mailboxes
+.It
+feed entries turn into internet messages
+.It
+read/unread state like normal mail
+.It
+reply or forward feed entries as email
+.It
+all state in IMAP, easy to cron
+.El
diff --git a/txt/shows.txt b/txt/shows.txt
new file mode 100644
index 00000000..62e6a071
--- /dev/null
+++ b/txt/shows.txt
@@ -0,0 +1,32 @@
+2020-01-23 (La Sala Rossa) Secondsight, BIG|BRAVE
+2019-12-10 (Casa del Popolo) meth, Street Sects
+2019-06-22 (Casa del Popolo) Persons Unknown, Palissade, Police des Moeurs, Blu Anxiety
+2019-06-22 (Bar Le Ritz) Cloakroom, Pelican
+2019-06-21 (La Vitrola) Leash Aggression, CPU Rave, Vitex, Pinocchio
+2019-06-20 (Casa del Popolo) Beep Test, Liar//Lier, Wetware
+2019-06-18 (Casa del Popolo) Nomadic War Machine; it foot, it ears; Wendy Eisenberg
+2019-06-17 (La Sala Rossa) SaskPWR, Lubomyr Melnyk, Architek Percussion (Nicole Lizée)
+2019-06-08 (La Sotterenea) Eliza Kavtion, Beep Test, Dri Hiev
+2019-05-03 (Turbo Haüs) Issfenn
+2019-04-21 (Bar Le Ritz PDB) Claud, Hatchie, Girlpool
+2018-11-14 (Turbo Haus) Juss, Street Sects
+2018-07-26 (Theatre Fairmount) Uniform, Deafheaven
+2018-06-14 (Casa del Popolo) Markus Floats, Mark Lowe, Carodiaro, Eliza Kavtion
+2018-04-26 (Bar Le Ritz PDB) Strega, Show of Bedlam, Rosetta
+2018-04-13 (La Vitrola) Eliza Kavtion, Lungbutter, Wrekmeister Harmonies
+2018-03-08 (Brasserie Beaubien) Clayborne, Nightwitches, Aseethe, Vile Creature
+2018-02-08 (Bar Le Ritz PDB) KGD, Efrim Manuel Menuck
+2017-09-30 (La Sala Rossa) Truster, Lungbutter, Big Brave
+2017-09-19 (La Vitrola) Saccharine, Xiu Xiu
+2017-06-01 (Casa del Popolo) Genevieve Heistek, Saltland
+2017-05-27 (l’Escogriffe) Sough, Ikaray, C H R I S T
+2017-05-14 (Bar Le Ritz PDB) Mutter’d, Aim Low, Wrekmeister Harmonies
+2016-09-25 (La Sala Rossa) Cloud Rat, Wolves in the Throne Room
+2016-09-21 (Theatre Paradoxe) Godspeed You! Black Emperor
+2016-04-08 (La Sala Rossa) Caro Diaro, Wreckage With Stick, Ought
+2015-08-13 (La Vitrola) Gutser, Chemical Way, Saul Hittner, In the Name of Havoc
+2015-06-10 (La Sala Rossa) Ryan Sawyer, Colin Stetson & Sarah Neufeld
+2015-06-09 (La Sala Rossa) The Mile End Ladies String Auxiliary, Christof Migone
+2015-06-08 (Casa del Popolo) C H R I S T, Jessica Moss, Big Brave
+2014-01-19 (Metropolis) Godspeed You! Black Emperor
+2014-01-18 (l’Olympia) Elf Power, Neutral Milk Hotel
diff --git a/txt/trouble-at-jinx-hotel.txt b/txt/trouble-at-jinx-hotel.txt
new file mode 100644
index 00000000..4db28dd6
--- /dev/null
+++ b/txt/trouble-at-jinx-hotel.txt
@@ -0,0 +1,236 @@
+mollasses
+
+...à l'hôtel jinx...
+
+thierry amar; flüffy erskine; norsola johnson; kate lawrence;
+jennifer ménard; mike moya; sam shalabi; scott lregrande chernoff...
+chris brokaw; bruce cawdron; david michael curry; lisa gamble; efrim
+menuck; michel meunier; js truchy; thalia zedek... à l'hôtel jinx.
+
+lucky 13: siren's song. la la la, amerika. Saint Christopher's
+blues.  sign of judgment. Lynn Canyon wedding song. coda. You Can't
+Win. trouble in mind. las niñas. Miss Peach's Pawnshop. buffaloed
+at Wounded Knee/the weeping winds. no love lost. songs from the
+basement.
+
+trouble at jinx hotel. these cursed recordings began in late winter
+2003 at the hotel2tango in montréal. it was a bitter sunday in
+march. the world was on the brink of war in old mesopotamia, and
+we were all of us sick with the influenza. headaches. fevers. wrecked
+guts and water on the lungs. coughing like crazy. everyone with a
+base case of the shakes.  the hotel wass cold and its ghosts were
+unhappy. electricity was being weird. lights flickered and all the
+microphones crackled with live current. little blue sparks dancing
+through the studio rooms. amplifiers were picking up strange radio
+frequencies and the piano, which couldn't hold a tune to save its
+own life, was behaving like a cantankerous old man. our cats and
+dogs were nervous and excited, a-jitter the way animals get whenever
+catastrope looms. we started with a 16-track tape machine, three
+spools of 1/4" analog audio tape, and a lucky thirteen little songs
+hanging in our heads. but when the 16-track busted and broke down
+a few days later, we moved to 2" tape on a 24-track machine and
+began anew with our fingers crossed. then the 24-track showed the
+first symptoms of its own terrible illness. so we did what we could
+with digital audio tape while our trusty friend and technician,
+garfield lamb, nursed the equipment back to some semblance of health.
+then we transfered the digital recordings to 2" tape and went to
+work again...  waiting to see what the gods would do next. they
+toyed with us for a while before unleashing their full fury: the
+24-track, seizing mid-song one evening, ate a reel of tape and sent
+it spewing around the studio in little pieces, a scene as cruel as
+confetti at a funeral.  garfield somehow managed to splice the tape
+together again. but our nerves were now in tatters too, scattered
+all over the hotel floor. when we finally finished tracking this
+music in the summer of 2003, the cats and dogs didn't look any less
+worried than when we'd begun. of course, they sensed the disaster
+we would soon see for ourselves: as we started mixing the very next
+night, a faulty lamp at the studio short-circuited and the tape
+machine caught on fire. a freak electrical accident. there was an
+asterisk of light; then a dragon-tail of smoke coiling across the
+room; then there was a darkness; and then the 24-track quietly died.
+the animals, cowering in corners, whined, *why didn't you fucking
+fools jump ship at the first sign of the storm*? that's when we
+drifted away from the jinxed hotel... floating until we found safe
+harbour in a studio we could borrow for a few days - one whose own
+resident dogs, zoro and ciska, greeted us with idiot grins and the
+contented looks of drunken sailors on calm seas. mixing was finished
+in a kind of delirious distress at MixArt in notre-dame-de-grace,
+montréal, autumn 2003. these lucky thirteen. dieu merci. slgc. *new
+year's eve* 2003.
+
+siren's song. instrumental.
+
+la la la, amerika. amerika is crawling with cops tonight as we put
+our fists through the windows of the world i know you're broken and
+you're down at the mouth but you're pouting like a punished little
+girl when darkness calls night falls oh mother where are the children
+you've orphaned all over the Earth we're frightened and sickened
+and poverty-stricken and waiting for you to send word when darkness
+calls the sky falls we're tired mother and we're poor we're wretched
+at your teeming shore we're homeless and tossed by the storm looking
+for the light at your golden door when darkness calls night falls.
+
+flüffy: marching drum, percussion & choir; norsola: cello & voice;
+kate: violin; jennifer: voice; moya: Crumar organ; dmc: viola &
+choir; gamble: choir; efrim: choir; js: upright bass; thalia: voice;
+scott: acoustic guitars & vocals; scott recorded the air-raid siren
+and bombs on the nightly news when baghdad was attacked by the
+united states and great britain in march 2003; words & music by
+scott chernoff, as stolen from the inscription on the statue of
+liberty: *give me your tired your poor your huddled masses yearning
+to breathe the wretched refuse of your teeming shore send these the
+homeless tempest-tossed to me i lift my lamp beside the golden
+door*.
+
+Saint Christopher's blues. the locusts are in the jimson Shit Creek
+is on the rise and you're out wrecking eternity this town looks
+like a prison in September's crimson sky when i should be loving
+you perfectly you're such a pretty little mess with your Saint
+Christopher blues and that doomed little look in your eye the weight
+of the world rests all upon your tiny shoes but June why are you
+so terrified give me the locust and the flood i'm a Fool for Love
+but i'm kneeling in Shit Creek tonight.
+
+thierry: upright & electric bass; flüffy: marching drum; kate:
+violin; jennifer: voice; moya: piano & Crumar organ; bruce: drums;
+gramble: scrap metal; scott: electric guitar & vocals. words & music
+by scott chernoff.
+
+sign of judgment. yes sign of judgment yes sign of judgment yes
+sign of judgment time ain't long i don't like old Satan none of his
+tempting charms cheats you at your Jesus now and roll you in his
+arms yes sign of judgment yes sign of judgment yes sign of judgment
+time ain't long i don't like old Satan nothing he say or do tell
+one lie to hurt us all and two to make it true yes sign of judgment
+yes sign of judgment yes sign of judgment time ain't long.
+
+norsola: cello; jennifer: voice; efrim: electric guitar & harmonium;
+js: upright bass; thalia: voice; scott: acoustic guitar & vocals.
+words & music by kid prince moore (traditional).
+
+Lynn Canyon wedding song. well i never cared very much for the west
+except for you there who i loved the best now please take me back
+east i wrote your name in silver and green where Love and Hate Play
+with Fate and History now please take me back east oh please take
+me back east we came to the Canyon across the calm and the wild
+from Mountain to Mountain and Island to aisle i came for Abel you
+came for Cain and we danced on the tables between the cradle and
+the grave and i never cared very much for the west but i will be
+there in my Sunday best if you will wear your red wedding dress
+then please take me back east oh please take me back east.
+
+flüffy: saw; jennifer: voice; moya: piano & Crumar organ; dmc: viola
+& saw; js: upright bass & voice; scott: acoustic guitar & vocals.
+words & music by scott chernoff.
+
+coda. instrumental.
+
+flüffy: metal heating duct; michel: banjo; dog & voice drone recorded
+by julian evans on video tape at Lynn Canyon 2002; mixed by scott
+& harris newman in montréal 2003.
+
+You Can't Win. you with your railroad bones and you with your
+golden-spiked skin you with the wind in your clothes and your hat
+like a house caving in oh man You Can't Win oh man You Can't Win
+oh man You Can't Win when the Angel of Light is at the window with
+the Sanctimonious Kid when you're down and out from Sacramento on
+the New York City skids oh man You Can't Win oh man You Can't Win
+oh man You Can't Win when the East River is groaning all below the
+Williamsburg Bridge when airplanes are exploding in the skyline's
+falling limbs oh man You Can't Win oh man You Can't Win oh man You
+Can't Win when the Swans are at your throat with their busted burning
+wings when they squeal and scream and moan at every last ship that
+comes in oh man You Can't Win oh man You Can't Win oh man You Can't
+Win.
+
+flüffy: chor; norsola: choir; jennifer: voice; moya: electric guitars
+& Crumar organ; sam: oud; bruce: drums & marimba; dmc: choir;
+gramble: scrap metal & choir; efrim: electric guitar & choir; js:
+choir; thalia: choir; scott: electric & acoustic guitars, vocals.
+words & music by scott chernoff, on the road from sacramento to
+nyc. september 11 2001, while reading jack black's 1926 hobo memoir
+*You Can't Win* and listening to the music of michael gira..
+
+trouble in mind. trouble in mind i'm blue but i won't be blue all
+the way you know that sun is gonna shine on me someday i'm gonna
+lay my head on some lonesome railroad line and let that big
+motherfucking engine nullify my mind trouble in mind i'm blue but
+i won't be blue all the way you know that sun is gonna shine on me
+someday.
+
+jennifer: voice; sam: electric guitars; chris: electric guitar;
+scott: acoustic guitar & vocals. words & music traditional, as
+learned from a 1960s  recording by sam lightnin' hopkins.
+
+las niñas. instrumental.
+
+andrew mayrs recorded his baby daughter illimani crying while banging
+on a piano in kitsilano, vancouver 2003; screaming children recorded
+by scott at rue roy, montréal 2003. mixed by scott & harris newman
+in montréal 2003.
+
+Miss Peach's Pawnshop. i bought this cross on the island of St.
+Thomas because i wanted jesus on my chest i got this tattoo in New
+Orleans and this one in the Orient for my honeymoon and i got this
+scar somewhere far far away i was drunk as hell and i tried to walk
+home and my hands were broken and i found this prayer in the back
+of a magazine i know it's ripped but it came like this it came like
+this i bought this song at Miss Peach's Pawn with this old overcoat
+and a gold-plated wristwatch and i found this prayer in the back
+of a magazine i know it's ripped but it came like this it came like
+this it came like this it came like this.
+
+norsola: cello; kate: violin; jennifer: voice; moya: electric guitar,
+piano & Crumar organ; dmc: viola; js: upright bass; scott: acoustic
+guitar & vocals. words by hilary peach & scott chernoff; music by
+scott chernoff. this is a bastard adaptation of peach's poem *Tattoo*
+from her album, *Poems Only Dogs Can Hear*.
+
+buffaloed at Wounded Knee/the weeping winds. instrumental. (for
+l.p. & a.i.m. and a pox on mean-spirited sons of bitches everywhere).
+
+flüffy: saws; dmc: saws.
+
+no love lost. good-bye old friend it's time to go this is the end
+of all that we know when you worship in the house of burden i worship
+in the house of blame as you learn to let your spirit burn i yearn
+to be a flame to be a flame and there's no love no love lost as
+there is the righteous there is the wrong and there is the night
+which is betrayed by the dawn and there's no love no love lost as
+there is the sinner there is the god and there is the singer profaned
+by the song and there's no love no love lost there's no love no
+love lost.
+
+thierry: electric bass; flüffy: bowed piano & saws; jennifer: voice;
+moya: piano; michel: banjo; thalia: voice; scott: acoustic guitar,
+bowed piano & vocals. words & music by scott chernoff.
+
+songs from the basement. there's a song for hatred and a song for
+love a song for betrayal and a song for trust there's a song for
+what's fated a song for dumb luck a song for what's sacred and one
+for what's fucked there's a song which is prayed a song which is
+cussed these songs from the basement which play unto us.
+
+norsola: cello; kate: violin; jennifer: voice; sam: electric guitars;
+bruce: marimba & cymbals; dmc: viola; efrim: harmonium; garfield
+lamb: knife; scott: acoustic guitar & vocals. words & music by scott
+chernoff.  mixed by howard bilerman at the hotel... ...after the
+storm had all blown by...
+
+recorded by howard bilerman, efrim & scott at mom & pop sounds in
+the hotel2tango, mile end, montréal 2003. except where noted,
+everything was mixed by howard bilerman & molasses at MixArt in
+notre-dame-de-grace, montréal 2003. mastered by harris newman in
+little italy, montréal 2003 & 2004. all songs c&p SOCAN 2004, except
+*sign of judgment* & *trouble in mind* which are in the public
+domain. hilary peach's poem *Tattoo*, which inspired *Miss Peach's
+Pawnshop*, is c&p hilary peach 2003. all music arranged by molasses,
+design and hand-lettering by slgc ink. in tokyo. photography by dmc
+& norsola. layout by slgc ink. with assistance by sean o'hara. all
+love to those who helped: sohara & gary at alien8 recordings; howard
+bilerman; cada del popolo; don & ian at constellation; eric craven;
+julian evans; michael feuerstack; aidan girt; lea grahovac; taras
+grescoe; garfield lamb; tim mahony; andrew mayrs, vally mendoza &
+illimani mendoza-mayrs; boris & nicolas at MixArt; harris newman,
+*who is never wrong*; hilary peach; sugar & smokey; and all the
+cars and dogs... xoxo...
diff --git a/txt/tweets.txt b/txt/tweets.txt
new file mode 100644
index 00000000..240351ec
--- /dev/null
+++ b/txt/tweets.txt
@@ -0,0 +1,32 @@
+triangle forum
+https://twitter.com/g0m/status/963890156477603841
+
+damn ya ass fat what's ya pronouns?
+https://twitter.com/msbigmilk/status/1291218055939448833
+
+afab
+https://twitter.com/ErisGael/status/1257524779046907904
+
+chaos emeralds
+https://twitter.com/ErisGael/status/1190147736244490240
+
+might as well salivate
+https://twitter.com/prawn_meat/status/857444039833944064
+
+notifications
+https://twitter.com/WTMMP/status/1259694226595610629
+
+all robot & computers
+https://twitter.com/cryptcrier/status/1238339418160680960
+
+the wet world
+https://twitter.com/TragicAllyHere/status/1137187876507140098
+
+a purchase?
+https://twitter.com/pant_leg/status/1027693563604230144
+
+influencer
+https://twitter.com/witchpuppy/status/974690828257054721
+
+-Wint-conversion
+https://twitter.com/jckarter/status/967802665080995840
diff --git a/www/causal.agency/.gitignore b/www/causal.agency/.gitignore
new file mode 100644
index 00000000..7935a3c1
--- /dev/null
+++ b/www/causal.agency/.gitignore
@@ -0,0 +1,3 @@
+*.html
+scheme.css
+scheme.png
diff --git a/www/causal.agency/Makefile b/www/causal.agency/Makefile
new file mode 100644
index 00000000..95f52120
--- /dev/null
+++ b/www/causal.agency/Makefile
@@ -0,0 +1,20 @@
+WEBROOT = /usr/local/www/causal.agency
+
+FILES = index.html style.css scheme.css scheme.png
+
+all: ${FILES}
+
+index.html: index.7
+	mandoc -T html -O style=style.css index.7 > index.html
+
+scheme.css:
+	scheme -st > scheme.css
+
+scheme.png:
+	scheme -g > scheme.png
+
+install: ${FILES}
+	install -C -m 644 ${FILES} ${WEBROOT}
+
+clean:
+	rm -f index.html scheme.css scheme.png
diff --git a/www/causal.agency/index.7 b/www/causal.agency/index.7
new file mode 100644
index 00000000..489b0b53
--- /dev/null
+++ b/www/causal.agency/index.7
@@ -0,0 +1,70 @@
+.Dd May 19, 2021
+.Dt CAUSAL.AGENCY 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm june
+.Nd computer enthusiast!!
+.
+.Sh SYNOPSIS
+.Nm mail
+.Mt june@causal.agency
+.Nm
+in
+.Li #ascii.town
+on tilde.chat
+.
+.Sh DESCRIPTION
+I make mostly IRC software in C.
+I like
+.Fx
+and
+.Ox
+but also the GPL.
+I want to learn to talk to strangers
+and seek out as much magic as I can.
+.
+.Pp
+.Lk https://git.causal.agency code
+\(em
+.Lk https://text.causal.agency words
+.Pq Lk gopher://text.causal.agency gopher
+\(em
+.Lk /list/ mailist
+\(em
+.Lk https://liberapay.com/june/ liberapay
+.
+.Pp
+These are some things I've done:
+.Bl -tag -width Ds
+.It Lk https://git.causal.agency/pounce/about pounce
+a multi-client-first IRC bouncer
+.It Lk https://git.causal.agency/catgirl/about catgirl
+a cosy IRC client
+.It Lk https://git.causal.agency/litterbox/about litterbox
+a full-text search IRC logger
+.It Lk https://git.causal.agency/scooper/about scooper
+a web interface for litterbox
+.It Lk https://git.causal.agency/catsit/about catsit
+a process supervisor
+.It Lk https://git.causal.agency/imbox/about "imbox & git-fetch-email"
+a tool to pull patches out of IMAP
+.It Lk https://git.causal.agency/bubger/about bubger
+a mailing list archive generator for IMAP
+.It Lk https://git.causal.agency/notemap/about notemap
+a tool to mirror text files to IMAP notes
+.It Lk https://ascii.town/explore.html torus@ascii.town
+a collaborative ASCII art project
+.It Lk ssh://play@ascii.town play@ascii.town
+a 2048 and snake game over
+.Xr ssh 1
+.It Lk https://git.causal.agency/cards/about cards
+a
+.Pa CARDS.DLL
+loader for SDL
+.It Lk scheme.png scheme
+an earthy terminal colour scheme
+.El
+.
+.Sh SEE ALSO
+.Lk /bin/ bin
diff --git a/www/causal.agency/style.css b/www/causal.agency/style.css
new file mode 100644
index 00000000..368d8da1
--- /dev/null
+++ b/www/causal.agency/style.css
@@ -0,0 +1,23 @@
+@import url("scheme.css");
+
+table.head, table.foot { width: 100%; }
+td.head-rtitle, td.foot-os { text-align: right; }
+td.head-vol { text-align: center; }
+div.Pp { margin: 1ex 0ex; }
+div.Nd, div.Bf, div.Op { display: inline; }
+span.Pa, span.Ad { font-style: italic; }
+span.Ms { font-weight: bold; }
+dl.Bl-diag > dt { font-weight: bold; }
+code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn,
+code.Cd { font-weight: bold; font-family: inherit; }
+
+html { font-family: monospace; line-height: 1.25em; }
+body { max-width: 80ch; margin: 1em auto; padding: 0 1ch; }
+table { border-collapse: collapse; }
+table.Nm code.Nm { padding-right: 1ch; }
+table.foot { margin-top: 1em; }
+
+html { background-color: var(--ansi16); color: var(--ansi17); }
+a { color: var(--ansi4); }
+a:visited { color: var(--ansi5); }
+a.permalink { color: var(--ansi3); text-decoration: none; }
diff --git a/www/git.causal.agency/.gitignore b/www/git.causal.agency/.gitignore
new file mode 100644
index 00000000..a0ae074c
--- /dev/null
+++ b/www/git.causal.agency/.gitignore
@@ -0,0 +1,6 @@
+about-filter
+hilex
+htagml
+mtags
+owner-filter
+source-filter
diff --git a/www/git.causal.agency/Makefile b/www/git.causal.agency/Makefile
new file mode 100644
index 00000000..638c21e7
--- /dev/null
+++ b/www/git.causal.agency/Makefile
@@ -0,0 +1,20 @@
+ETC = /usr/local/etc
+WWW = /usr/local/www/cgit
+LIBEXEC = /usr/local/libexec
+
+BIN = ../../bin
+BINS = about-filter source-filter owner-filter hilex htagml mtags
+
+all: ${BINS}
+
+install: cgitrc custom.css ${BINS}
+	install -m 644 cgitrc ${ETC}
+	install -m 644 custom.css ${WWW}
+	install ${BINS} ${LIBEXEC}
+
+hilex htagml mtags::
+	${MAKE} -C ${BIN} $@
+	ln -f ${BIN}/$@ $@
+
+clean:
+	rm -f ${BINS}
diff --git a/www/git.causal.agency/about-filter.sh b/www/git.causal.agency/about-filter.sh
new file mode 100644
index 00000000..2ff645e2
--- /dev/null
+++ b/www/git.causal.agency/about-filter.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+options=fragment,man=%N.%S,includes=../tree/%I
+
+case "$1" in
+	(README.[1-9])
+		exec /usr/bin/mandoc -T html -O $options
+		;;
+	(*.[1-9])
+		exec /usr/bin/mandoc -T html -O $options,toc
+		;;
+	(*)
+		exec /usr/local/libexec/hilex -l text -f html -o pre
+		;;
+esac
diff --git a/www/git.causal.agency/cgit/.gitignore b/www/git.causal.agency/cgit/.gitignore
new file mode 100644
index 00000000..bca98fcf
--- /dev/null
+++ b/www/git.causal.agency/cgit/.gitignore
@@ -0,0 +1,13 @@
+# Files I don't care to see in git-status/commit
+/cgit
+/git
+cgit.conf
+CGIT-CFLAGS
+VERSION
+cgitrc.5
+cgitrc.5.fo
+cgitrc.5.html
+cgitrc.5.pdf
+cgitrc.5.xml
+*.o
+*.d
diff --git a/.mailmap b/www/git.causal.agency/cgit/.mailmap
index 03b54796..03b54796 100644
--- a/.mailmap
+++ b/www/git.causal.agency/cgit/.mailmap
diff --git a/AUTHORS b/www/git.causal.agency/cgit/AUTHORS
index 031de338..031de338 100644
--- a/AUTHORS
+++ b/www/git.causal.agency/cgit/AUTHORS
diff --git a/COPYING b/www/git.causal.agency/cgit/COPYING
index d159169d..d159169d 100644
--- a/COPYING
+++ b/www/git.causal.agency/cgit/COPYING
diff --git a/Makefile b/www/git.causal.agency/cgit/Makefile
index d13c5bd1..358a3c8e 100644
--- a/Makefile
+++ b/www/git.causal.agency/cgit/Makefile
@@ -15,7 +15,7 @@ pdfdir = $(docdir)
 mandir = $(prefix)/share/man
 SHA1_HEADER = <openssl/sha.h>
 GIT_VER = 2.32.0
-GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.xz
+GIT_URL = https://www.kernel.org/pub/software/scm/git/git-$(GIT_VER).tar.gz
 INSTALL = install
 COPYTREE = cp -r
 MAN5_TXT = $(wildcard *.5.txt)
@@ -157,7 +157,7 @@ clean-doc:
 	$(RM) cgitrc.5 cgitrc.5.html cgitrc.5.pdf cgitrc.5.xml cgitrc.5.fo
 
 get-git:
-	curl -L $(GIT_URL) | tar -xJf - && rm -rf git && mv git-$(GIT_VER) git
+	curl -L $(GIT_URL) | tar -xzf - && rm -rf git && mv git-$(GIT_VER) git
 
 tags:
 	$(QUIET_TAGS)find . -name '*.[ch]' | xargs ctags
diff --git a/README b/www/git.causal.agency/cgit/README
index 7a6b4a40..371cf21f 100644
--- a/README
+++ b/www/git.causal.agency/cgit/README
@@ -32,18 +32,6 @@ This will install `cgit.cgi` and `cgit.css` into `/var/www/htdocs/cgit`. You
 can configure this location (and a few other things) by providing a `cgit.conf`
 file (see the Makefile for details).
 
-If you'd like to compile without Lua support, you may use:
-
-    $ make NO_LUA=1
-
-And if you'd like to specify a Lua implementation, you may use:
-
-    $ make LUA_PKGCONFIG=lua5.1
-
-If this is not specified, the Lua implementation will be auto-detected,
-preferring LuaJIT if many are present. Acceptable values are generally "lua",
-"luajit", "lua5.1", and "lua5.2".
-
 
 Dependencies
 ------------
@@ -51,7 +39,6 @@ Dependencies
 * libzip
 * libcrypto (OpenSSL)
 * libssl (OpenSSL)
-* optional: luajit or lua, most reliably used when pkg-config is available
 
 Apache configuration
 --------------------
diff --git a/cache.c b/www/git.causal.agency/cgit/cache.c
index 55199e8f..578b73b0 100644
--- a/cache.c
+++ b/www/git.causal.agency/cgit/cache.c
@@ -265,6 +265,13 @@ static int process_slot(struct cache_slot *slot)
 {
 	int err;
 
+	/*
+	 * Make sure any buffered data is flushed before we redirect,
+	 * do sendfile(2) or write(2)
+	 */
+	if (fflush(stdout))
+		return errno;
+
 	err = open_slot(slot);
 	if (!err && slot->match) {
 		if (is_expired(slot)) {
diff --git a/cache.h b/www/git.causal.agency/cgit/cache.h
index 470da4fc..470da4fc 100644
--- a/cache.h
+++ b/www/git.causal.agency/cgit/cache.h
diff --git a/cgit.c b/www/git.causal.agency/cgit/cgit.c
index 08d81a1d..a86970de 100644
--- a/cgit.c
+++ b/www/git.causal.agency/cgit/cgit.c
@@ -674,7 +674,7 @@ static inline void authenticate_post(void)
 		len = MAX_AUTHENTICATION_POST_BYTES;
 	if ((len = read(STDIN_FILENO, buffer, len)) < 0)
 		die_errno("Could not read POST from stdin");
-	if (write(STDOUT_FILENO, buffer, len) < 0)
+	if (fwrite(buffer, 1, len, stdout) < len)
 		die_errno("Could not write POST to stdout");
 	cgit_close_filter(ctx.cfg.auth_filter);
 	exit(0);
@@ -964,12 +964,6 @@ static void cgit_parse_args(int argc, const char **argv)
 	for (i = 1; i < argc; i++) {
 		if (!strcmp(argv[i], "--version")) {
 			printf("CGit %s | https://git.zx2c4.com/cgit/\n\nCompiled in features:\n", CGIT_VERSION);
-#ifdef NO_LUA
-			printf("[-] ");
-#else
-			printf("[+] ");
-#endif
-			printf("Lua scripting\n");
 #ifndef HAVE_LINUX_SENDFILE
 			printf("[-] ");
 #else
@@ -1051,7 +1045,6 @@ int cmd_main(int argc, const char **argv)
 	const char *path;
 	int err, ttl;
 
-	cgit_init_filters();
 	atexit(cgit_cleanup_filters);
 
 	prepare_context();
diff --git a/cgit.css b/www/git.causal.agency/cgit/cgit.css
index dfa144d0..f3dbb7a9 100644
--- a/cgit.css
+++ b/www/git.causal.agency/cgit/cgit.css
@@ -75,7 +75,7 @@ div#cgit table.tabs td {
 }
 
 div#cgit table.tabs td a {
-	padding: 2px 0.75em;
+	padding: 2px 0.25em;
 	color: #777;
 	font-size: 110%;
 }
@@ -437,11 +437,6 @@ div#cgit div.commit-subject {
 	padding: 0em;
 }
 
-div#cgit div.commit-msg {
-	white-space: pre;
-	font-family: monospace;
-}
-
 div#cgit div.notes-header {
 	font-weight: bold;
 	padding-top: 1.5em;
@@ -538,26 +533,20 @@ div#cgit table.diff {
 	width: 100%;
 }
 
-div#cgit table.diff td {
-	font-family: monospace;
-	white-space: pre;
-}
-
-div#cgit table.diff td div.head {
+div#cgit table.diff td span.head {
 	font-weight: bold;
-	margin-top: 1em;
 	color: black;
 }
 
-div#cgit table.diff td div.hunk {
+div#cgit table.diff td span.hunk {
 	color: #009;
 }
 
-div#cgit table.diff td div.add {
+div#cgit table.diff td span.add {
 	color: green;
 }
 
-div#cgit table.diff td div.del {
+div#cgit table.diff td span.del {
 	color: red;
 }
 
@@ -581,7 +570,6 @@ div#cgit table.list td.reposection {
 
 div#cgit a.button {
 	font-size: 80%;
-	padding: 0em 0.5em;
 }
 
 div#cgit a.primary {
@@ -671,7 +659,6 @@ div#cgit div.footer a:hover {
 
 div#cgit a.branch-deco {
 	color: #000;
-	margin: 0px 0.5em;
 	padding: 0px 0.25em;
 	background-color: #88ff88;
 	border: solid 1px #007700;
@@ -679,7 +666,6 @@ div#cgit a.branch-deco {
 
 div#cgit a.tag-deco {
 	color: #000;
-	margin: 0px 0.5em;
 	padding: 0px 0.25em;
 	background-color: #ffff88;
 	border: solid 1px #777700;
@@ -687,7 +673,6 @@ div#cgit a.tag-deco {
 
 div#cgit a.tag-annotated-deco {
 	color: #000;
-	margin: 0px 0.5em;
 	padding: 0px 0.25em;
 	background-color: #ffcc88;
 	border: solid 1px #777700;
@@ -695,7 +680,6 @@ div#cgit a.tag-annotated-deco {
 
 div#cgit a.remote-deco {
 	color: #000;
-	margin: 0px 0.5em;
 	padding: 0px 0.25em;
 	background-color: #ccccff;
 	border: solid 1px #000077;
@@ -703,7 +687,6 @@ div#cgit a.remote-deco {
 
 div#cgit a.deco {
 	color: #000;
-	margin: 0px 0.5em;
 	padding: 0px 0.25em;
 	background-color: #ff8888;
 	border: solid 1px #770000;
@@ -714,7 +697,6 @@ div#cgit div.commit-subject a.tag-deco,
 div#cgit div.commit-subject a.tag-annotated-deco,
 div#cgit div.commit-subject a.remote-deco,
 div#cgit div.commit-subject a.deco {
-	margin-left: 1em;
 	font-size: 75%;
 }
 
diff --git a/cgit.h b/www/git.causal.agency/cgit/cgit.h
index 69b5c132..72fcd849 100644
--- a/cgit.h
+++ b/www/git.causal.agency/cgit/cgit.h
@@ -385,7 +385,6 @@ extern void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char
 extern void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv);
 extern struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype);
 extern void cgit_cleanup_filters(void);
-extern void cgit_init_filters(void);
 
 extern void cgit_prepare_repo_env(struct cgit_repo * repo);
 
diff --git a/cgit.mk b/www/git.causal.agency/cgit/cgit.mk
index 3fcc1ca3..5b9ed5be 100644
--- a/cgit.mk
+++ b/www/git.causal.agency/cgit/cgit.mk
@@ -27,32 +27,6 @@ ifdef NO_C99_FORMAT
 	CFLAGS += -DNO_C99_FORMAT
 endif
 
-ifdef NO_LUA
-	LUA_MESSAGE := linking without specified Lua support
-	CGIT_CFLAGS += -DNO_LUA
-else
-ifeq ($(LUA_PKGCONFIG),)
-	LUA_PKGCONFIG := $(shell for pc in luajit lua lua5.2 lua5.1; do \
-			$(PKG_CONFIG) --exists $$pc 2>/dev/null && echo $$pc && break; \
-			done)
-	LUA_MODE := autodetected
-else
-	LUA_MODE := specified
-endif
-ifneq ($(LUA_PKGCONFIG),)
-	LUA_MESSAGE := linking with $(LUA_MODE) $(LUA_PKGCONFIG)
-	LUA_LIBS := $(shell $(PKG_CONFIG) --libs $(LUA_PKGCONFIG) 2>/dev/null)
-	LUA_CFLAGS := $(shell $(PKG_CONFIG) --cflags $(LUA_PKGCONFIG) 2>/dev/null)
-	CGIT_LIBS += $(LUA_LIBS)
-	CGIT_CFLAGS += $(LUA_CFLAGS)
-else
-	LUA_MESSAGE := linking without autodetected Lua support
-	NO_LUA := YesPlease
-	CGIT_CFLAGS += -DNO_LUA
-endif
-
-endif
-
 # Add -ldl to linker flags on systems that commonly use GNU libc.
 ifneq (,$(filter $(uname_S),Linux GNU GNU/kFreeBSD))
 	CGIT_LIBS += -ldl
@@ -130,7 +104,6 @@ $(CGIT_OBJS): %.o: %.c GIT-CFLAGS $(CGIT_PREFIX)CGIT-CFLAGS $(missing_dep_dirs)
 	$(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) $(CGIT_CFLAGS) $<
 
 $(CGIT_PREFIX)cgit: $(CGIT_OBJS) GIT-LDFLAGS $(GITLIBS)
-	@echo 1>&1 "    * $(LUA_MESSAGE)"
 	$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) $(CGIT_LIBS)
 
 CGIT_SP_OBJS := $(patsubst %.o,%.sp,$(CGIT_OBJS))
diff --git a/cgit.png b/www/git.causal.agency/cgit/cgit.png
index 425528ee..425528ee 100644
--- a/cgit.png
+++ b/www/git.causal.agency/cgit/cgit.png
Binary files differdiff --git a/cgitrc.5.txt b/www/git.causal.agency/cgit/cgitrc.5.txt
index 33a6a8c0..8d663952 100644
--- a/cgitrc.5.txt
+++ b/www/git.causal.agency/cgit/cgitrc.5.txt
@@ -632,37 +632,6 @@ specification with the relevant string; available values are:
 'exec:'::
 	The default "one process per filter" mode.
 
-'lua:'::
-	Executes the script using a built-in Lua interpreter. The script is
-	loaded once per execution of cgit, and may be called multiple times
-	during cgit's lifetime, making it a good choice for repeated filters
-	such as the 'email filter'. It responds to three functions:
-
-	'filter_open(argument1, argument2, argument3, ...)'::
-		This is called upon activation of the filter for a particular
-		set of data.
-	'filter_write(buffer)'::
-		This is called whenever cgit writes data to the webpage.
-	'filter_close()'::
-		This is called when the current filtering operation is
-		completed. It must return an integer value. Usually 0
-		indicates success.
-
-	Additionally, cgit exposes to the Lua the following built-in functions:
-
-	'html(str)'::
-		Writes 'str' to the webpage.
-	'html_txt(str)'::
-		HTML escapes and writes 'str' to the webpage.
-	'html_attr(str)'::
-		HTML escapes for an attribute and writes "str' to the webpage.
-	'html_url_path(str)'::
-		URL escapes for a path and writes 'str' to the webpage.
-	'html_url_arg(str)'::
-		URL escapes for an argument and writes 'str' to the webpage.
-	'html_include(file)'::
-		Includes 'file' in webpage.
-
 
 Parameters are provided to filters as follows.
 
@@ -696,9 +665,6 @@ auth filter::
 	with a 302 redirect, and write to output one or more "Set-Cookie"
 	HTTP headers, each followed by a newline.
 
-	Please see `filters/simple-authentication.lua` for a clear example
-	script that may be modified.
-
 commit filter::
 	This filter is given no arguments. The commit message text that is to
 	be filtered is available on standard input and the filtered text is
diff --git a/cmd.c b/www/git.causal.agency/cgit/cmd.c
index 0eb75b1d..0eb75b1d 100644
--- a/cmd.c
+++ b/www/git.causal.agency/cgit/cmd.c
diff --git a/cmd.h b/www/git.causal.agency/cgit/cmd.h
index 6249b1d8..6249b1d8 100644
--- a/cmd.h
+++ b/www/git.causal.agency/cgit/cmd.h
diff --git a/configfile.c b/www/git.causal.agency/cgit/configfile.c
index e0391091..e0391091 100644
--- a/configfile.c
+++ b/www/git.causal.agency/cgit/configfile.c
diff --git a/configfile.h b/www/git.causal.agency/cgit/configfile.h
index af7ca197..af7ca197 100644
--- a/configfile.h
+++ b/www/git.causal.agency/cgit/configfile.h
diff --git a/contrib/hooks/post-receive.agefile b/www/git.causal.agency/cgit/contrib/hooks/post-receive.agefile
index 2f72ae9c..2f72ae9c 100755
--- a/contrib/hooks/post-receive.agefile
+++ b/www/git.causal.agency/cgit/contrib/hooks/post-receive.agefile
diff --git a/favicon.ico b/www/git.causal.agency/cgit/favicon.ico
index 56ff5938..56ff5938 100644
--- a/favicon.ico
+++ b/www/git.causal.agency/cgit/favicon.ico
Binary files differdiff --git a/www/git.causal.agency/cgit/filter.c b/www/git.causal.agency/cgit/filter.c
new file mode 100644
index 00000000..2b6c838e
--- /dev/null
+++ b/www/git.causal.agency/cgit/filter.c
@@ -0,0 +1,222 @@
+/* filter.c: filter framework functions
+ *
+ * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
+ *
+ * Licensed under GNU General Public License v2
+ *   (see COPYING for full license text)
+ */
+
+#include "cgit.h"
+#include "html.h"
+
+static inline void reap_filter(struct cgit_filter *filter)
+{
+	if (filter && filter->cleanup)
+		filter->cleanup(filter);
+}
+
+void cgit_cleanup_filters(void)
+{
+	int i;
+	reap_filter(ctx.cfg.about_filter);
+	reap_filter(ctx.cfg.commit_filter);
+	reap_filter(ctx.cfg.source_filter);
+	reap_filter(ctx.cfg.email_filter);
+	reap_filter(ctx.cfg.owner_filter);
+	reap_filter(ctx.cfg.auth_filter);
+	for (i = 0; i < cgit_repolist.count; ++i) {
+		reap_filter(cgit_repolist.repos[i].about_filter);
+		reap_filter(cgit_repolist.repos[i].commit_filter);
+		reap_filter(cgit_repolist.repos[i].source_filter);
+		reap_filter(cgit_repolist.repos[i].email_filter);
+		reap_filter(cgit_repolist.repos[i].owner_filter);
+	}
+}
+
+static int open_exec_filter(struct cgit_filter *base, va_list ap)
+{
+	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
+	int pipe_fh[2];
+	int i;
+
+	for (i = 0; i < filter->base.argument_count; i++)
+		filter->argv[i + 1] = va_arg(ap, char *);
+
+	chk_zero(fflush(stdout), "unable to flush STDOUT");
+	filter->old_stdout = chk_positive(dup(STDOUT_FILENO),
+		"Unable to duplicate STDOUT");
+	chk_zero(pipe(pipe_fh), "Unable to create pipe to subprocess");
+	filter->pid = chk_non_negative(fork(), "Unable to create subprocess");
+	if (filter->pid == 0) {
+		close(pipe_fh[1]);
+		chk_non_negative(dup2(pipe_fh[0], STDIN_FILENO),
+			"Unable to use pipe as STDIN");
+		execvp(filter->cmd, filter->argv);
+		die_errno("Unable to exec subprocess %s", filter->cmd);
+	}
+	close(pipe_fh[0]);
+	chk_non_negative(dup2(pipe_fh[1], STDOUT_FILENO),
+		"Unable to use pipe as STDOUT");
+	close(pipe_fh[1]);
+	return 0;
+}
+
+static int close_exec_filter(struct cgit_filter *base)
+{
+	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
+	int i, exit_status = 0;
+
+	chk_zero(fflush(stdout), "unable to flush STDOUT");
+	chk_non_negative(dup2(filter->old_stdout, STDOUT_FILENO),
+		"Unable to restore STDOUT");
+	close(filter->old_stdout);
+	if (filter->pid < 0)
+		goto done;
+	waitpid(filter->pid, &exit_status, 0);
+	if (WIFEXITED(exit_status))
+		goto done;
+	die("Subprocess %s exited abnormally", filter->cmd);
+
+done:
+	for (i = 0; i < filter->base.argument_count; i++)
+		filter->argv[i + 1] = NULL;
+	return WEXITSTATUS(exit_status);
+
+}
+
+static void fprintf_exec_filter(struct cgit_filter *base, FILE *f, const char *prefix)
+{
+	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
+	fprintf(f, "%sexec:%s\n", prefix, filter->cmd);
+}
+
+static void cleanup_exec_filter(struct cgit_filter *base)
+{
+	struct cgit_exec_filter *filter = (struct cgit_exec_filter *)base;
+	if (filter->argv) {
+		free(filter->argv);
+		filter->argv = NULL;
+	}
+	if (filter->cmd) {
+		free(filter->cmd);
+		filter->cmd = NULL;
+	}
+}
+
+static struct cgit_filter *new_exec_filter(const char *cmd, int argument_count)
+{
+	struct cgit_exec_filter *f;
+	int args_size = 0;
+
+	f = xmalloc(sizeof(*f));
+	/* We leave argv for now and assign it below. */
+	cgit_exec_filter_init(f, xstrdup(cmd), NULL);
+	f->base.argument_count = argument_count;
+	args_size = (2 + argument_count) * sizeof(char *);
+	f->argv = xmalloc(args_size);
+	memset(f->argv, 0, args_size);
+	f->argv[0] = f->cmd;
+	return &f->base;
+}
+
+void cgit_exec_filter_init(struct cgit_exec_filter *filter, char *cmd, char **argv)
+{
+	memset(filter, 0, sizeof(*filter));
+	filter->base.open = open_exec_filter;
+	filter->base.close = close_exec_filter;
+	filter->base.fprintf = fprintf_exec_filter;
+	filter->base.cleanup = cleanup_exec_filter;
+	filter->cmd = cmd;
+	filter->argv = argv;
+	/* The argument count for open_filter is zero by default, unless called from new_filter, above. */
+	filter->base.argument_count = 0;
+}
+
+int cgit_open_filter(struct cgit_filter *filter, ...)
+{
+	int result;
+	va_list ap;
+	if (!filter)
+		return 0;
+	va_start(ap, filter);
+	result = filter->open(filter, ap);
+	va_end(ap);
+	return result;
+}
+
+int cgit_close_filter(struct cgit_filter *filter)
+{
+	if (!filter)
+		return 0;
+	return filter->close(filter);
+}
+
+void cgit_fprintf_filter(struct cgit_filter *filter, FILE *f, const char *prefix)
+{
+	filter->fprintf(filter, f, prefix);
+}
+
+
+
+static const struct {
+	const char *prefix;
+	struct cgit_filter *(*ctor)(const char *cmd, int argument_count);
+} filter_specs[] = {
+	{ "exec", new_exec_filter },
+};
+
+struct cgit_filter *cgit_new_filter(const char *cmd, filter_type filtertype)
+{
+	char *colon;
+	int i;
+	size_t len;
+	int argument_count;
+
+	if (!cmd || !cmd[0])
+		return NULL;
+
+	colon = strchr(cmd, ':');
+	len = colon - cmd;
+	/*
+	 * In case we're running on Windows, don't allow a single letter before
+	 * the colon.
+	 */
+	if (len == 1)
+		colon = NULL;
+
+	switch (filtertype) {
+		case AUTH:
+			argument_count = 12;
+			break;
+
+		case EMAIL:
+			argument_count = 2;
+			break;
+
+		case OWNER:
+			argument_count = 0;
+			break;
+
+		case SOURCE:
+		case ABOUT:
+			argument_count = 1;
+			break;
+
+		case COMMIT:
+		default:
+			argument_count = 0;
+			break;
+	}
+
+	/* If no prefix is given, exec filter is the default. */
+	if (!colon)
+		return new_exec_filter(cmd, argument_count);
+
+	for (i = 0; i < ARRAY_SIZE(filter_specs); i++) {
+		if (len == strlen(filter_specs[i].prefix) &&
+		    !strncmp(filter_specs[i].prefix, cmd, len))
+			return filter_specs[i].ctor(colon + 1, argument_count);
+	}
+
+	die("Invalid filter type: %.*s", (int) len, cmd);
+}
diff --git a/filters/about-formatting.sh b/www/git.causal.agency/cgit/filters/about-formatting.sh
index 85daf9c2..85daf9c2 100755
--- a/filters/about-formatting.sh
+++ b/www/git.causal.agency/cgit/filters/about-formatting.sh
diff --git a/filters/commit-links.sh b/www/git.causal.agency/cgit/filters/commit-links.sh
index 796ac308..796ac308 100755
--- a/filters/commit-links.sh
+++ b/www/git.causal.agency/cgit/filters/commit-links.sh
diff --git a/filters/email-gravatar.py b/www/git.causal.agency/cgit/filters/email-gravatar.py
index d70440ea..012113c5 100755
--- a/filters/email-gravatar.py
+++ b/www/git.causal.agency/cgit/filters/email-gravatar.py
@@ -1,8 +1,5 @@
 #!/usr/bin/env python3
 
-# Please prefer the email-gravatar.lua using lua: as a prefix over this script. This
-# script is very slow, in comparison.
-#
 # This script may be used with the email-filter or repo.email-filter settings in cgitrc.
 #
 # The following environment variables can be used to retrieve the configuration
diff --git a/filters/html-converters/man2html b/www/git.causal.agency/cgit/filters/html-converters/man2html
index 0ef78841..0ef78841 100755
--- a/filters/html-converters/man2html
+++ b/www/git.causal.agency/cgit/filters/html-converters/man2html
diff --git a/filters/html-converters/md2html b/www/git.causal.agency/cgit/filters/html-converters/md2html
index 59f43a84..59f43a84 100755
--- a/filters/html-converters/md2html
+++ b/www/git.causal.agency/cgit/filters/html-converters/md2html
diff --git a/filters/html-converters/rst2html b/www/git.causal.agency/cgit/filters/html-converters/rst2html
index 02d90f81..02d90f81 100755
--- a/filters/html-converters/rst2html
+++ b/www/git.causal.agency/cgit/filters/html-converters/rst2html
diff --git a/filters/html-converters/txt2html b/www/git.causal.agency/cgit/filters/html-converters/txt2html
index 495eeceb..495eeceb 100755
--- a/filters/html-converters/txt2html
+++ b/www/git.causal.agency/cgit/filters/html-converters/txt2html
diff --git a/filters/syntax-highlighting.py b/www/git.causal.agency/cgit/filters/syntax-highlighting.py
index e912594c..e912594c 100755
--- a/filters/syntax-highlighting.py
+++ b/www/git.causal.agency/cgit/filters/syntax-highlighting.py
diff --git a/filters/syntax-highlighting.sh b/www/git.causal.agency/cgit/filters/syntax-highlighting.sh
index 840bc34f..840bc34f 100755
--- a/filters/syntax-highlighting.sh
+++ b/www/git.causal.agency/cgit/filters/syntax-highlighting.sh
diff --git a/gen-version.sh b/www/git.causal.agency/cgit/gen-version.sh
index 80cf49af..80cf49af 100755
--- a/gen-version.sh
+++ b/www/git.causal.agency/cgit/gen-version.sh
diff --git a/html.c b/www/git.causal.agency/cgit/html.c
index 7f81965f..cefcf5e7 100644
--- a/html.c
+++ b/www/git.causal.agency/cgit/html.c
@@ -80,7 +80,7 @@ char *fmtalloc(const char *format, ...)
 
 void html_raw(const char *data, size_t size)
 {
-	if (write(STDOUT_FILENO, data, size) != size)
+	if (fwrite(data, 1, size, stdout) != size)
 		die_errno("write error on html output");
 }
 
diff --git a/html.h b/www/git.causal.agency/cgit/html.h
index fa4de775..fa4de775 100644
--- a/html.h
+++ b/www/git.causal.agency/cgit/html.h
diff --git a/parsing.c b/www/git.causal.agency/cgit/parsing.c
index 72b59b3c..72b59b3c 100644
--- a/parsing.c
+++ b/www/git.causal.agency/cgit/parsing.c
diff --git a/robots.txt b/www/git.causal.agency/cgit/robots.txt
index 4ce948fe..1b33266d 100644
--- a/robots.txt
+++ b/www/git.causal.agency/cgit/robots.txt
@@ -1,3 +1,4 @@
 User-agent: *
 Disallow: /*/snapshot/*
+Disallow: /*/blame/*
 Allow: /
diff --git a/scan-tree.c b/www/git.causal.agency/cgit/scan-tree.c
index 6a2f65a8..6a2f65a8 100644
--- a/scan-tree.c
+++ b/www/git.causal.agency/cgit/scan-tree.c
diff --git a/scan-tree.h b/www/git.causal.agency/cgit/scan-tree.h
index 1afbd4bb..1afbd4bb 100644
--- a/scan-tree.h
+++ b/www/git.causal.agency/cgit/scan-tree.h
diff --git a/shared.c b/www/git.causal.agency/cgit/shared.c
index 8115469a..8115469a 100644
--- a/shared.c
+++ b/www/git.causal.agency/cgit/shared.c
diff --git a/tests/.gitignore b/www/git.causal.agency/cgit/tests/.gitignore
index 3fd2e965..3fd2e965 100644
--- a/tests/.gitignore
+++ b/www/git.causal.agency/cgit/tests/.gitignore
diff --git a/tests/Makefile b/www/git.causal.agency/cgit/tests/Makefile
index 65e11173..65e11173 100644
--- a/tests/Makefile
+++ b/www/git.causal.agency/cgit/tests/Makefile
diff --git a/tests/filters/dump.sh b/www/git.causal.agency/cgit/tests/filters/dump.sh
index da6f7a1b..da6f7a1b 100755
--- a/tests/filters/dump.sh
+++ b/www/git.causal.agency/cgit/tests/filters/dump.sh
diff --git a/tests/setup.sh b/www/git.causal.agency/cgit/tests/setup.sh
index 8db810ff..31e7d5bb 100755
--- a/tests/setup.sh
+++ b/www/git.causal.agency/cgit/tests/setup.sh
@@ -60,12 +60,6 @@ fi
 
 FILTER_DIRECTORY=$(cd ../filters && pwd)
 
-if cgit --version | grep -F -q "[+] Lua scripting"; then
-	export CGIT_HAS_LUA=1
-else
-	export CGIT_HAS_LUA=0
-fi
-
 mkrepo() {
 	name=$1
 	count=$2
@@ -144,19 +138,6 @@ repo.email-filter=exec:$FILTER_DIRECTORY/dump.sh
 repo.source-filter=exec:$FILTER_DIRECTORY/dump.sh
 repo.readme=master:a+b
 EOF
-
-	if [ $CGIT_HAS_LUA -eq 1 ]; then
-		cat >>cgitrc <<EOF
-repo.url=filter-lua
-repo.path=$PWD/repos/filter/.git
-repo.desc=filtered repo
-repo.about-filter=lua:$FILTER_DIRECTORY/dump.lua
-repo.commit-filter=lua:$FILTER_DIRECTORY/dump.lua
-repo.email-filter=lua:$FILTER_DIRECTORY/dump.lua
-repo.source-filter=lua:$FILTER_DIRECTORY/dump.lua
-repo.readme=master:a+b
-EOF
-	fi
 }
 
 cgit_query()
diff --git a/tests/t0001-validate-git-versions.sh b/www/git.causal.agency/cgit/tests/t0001-validate-git-versions.sh
index dd84fe3f..dd84fe3f 100755
--- a/tests/t0001-validate-git-versions.sh
+++ b/www/git.causal.agency/cgit/tests/t0001-validate-git-versions.sh
diff --git a/tests/t0010-validate-html.sh b/www/git.causal.agency/cgit/tests/t0010-validate-html.sh
index ca08d69d..ca08d69d 100755
--- a/tests/t0010-validate-html.sh
+++ b/www/git.causal.agency/cgit/tests/t0010-validate-html.sh
diff --git a/tests/t0020-validate-cache.sh b/www/git.causal.agency/cgit/tests/t0020-validate-cache.sh
index 657765d8..657765d8 100755
--- a/tests/t0020-validate-cache.sh
+++ b/www/git.causal.agency/cgit/tests/t0020-validate-cache.sh
diff --git a/tests/t0101-index.sh b/www/git.causal.agency/cgit/tests/t0101-index.sh
index 82ef9b04..82ef9b04 100755
--- a/tests/t0101-index.sh
+++ b/www/git.causal.agency/cgit/tests/t0101-index.sh
diff --git a/tests/t0102-summary.sh b/www/git.causal.agency/cgit/tests/t0102-summary.sh
index b8864cb1..b8864cb1 100755
--- a/tests/t0102-summary.sh
+++ b/www/git.causal.agency/cgit/tests/t0102-summary.sh
diff --git a/tests/t0103-log.sh b/www/git.causal.agency/cgit/tests/t0103-log.sh
index bdf1435a..bdf1435a 100755
--- a/tests/t0103-log.sh
+++ b/www/git.causal.agency/cgit/tests/t0103-log.sh
diff --git a/tests/t0104-tree.sh b/www/git.causal.agency/cgit/tests/t0104-tree.sh
index 2e140f59..2e140f59 100755
--- a/tests/t0104-tree.sh
+++ b/www/git.causal.agency/cgit/tests/t0104-tree.sh
diff --git a/tests/t0105-commit.sh b/www/git.causal.agency/cgit/tests/t0105-commit.sh
index 1a12ee39..cfed1e7d 100755
--- a/tests/t0105-commit.sh
+++ b/www/git.causal.agency/cgit/tests/t0105-commit.sh
@@ -11,7 +11,7 @@ test_expect_success 'find commit subject' '
 	grep "<div class=.commit-subject.>commit 5<" tmp
 '
 
-test_expect_success 'find commit msg' 'grep "<div class=.commit-msg.></div>" tmp'
+test_expect_success 'find commit msg' 'grep "<pre class=.commit-msg.></pre>" tmp'
 test_expect_success 'find diffstat' 'grep "<table summary=.diffstat. class=.diffstat.>" tmp'
 
 test_expect_success 'find diff summary' '
@@ -29,8 +29,8 @@ test_expect_success 'root commit contains diffstat' '
 '
 
 test_expect_success 'root commit contains diff' '
-	grep ">diff --git a/file-1 b/file-1<" tmp &&
-	grep "<div class=.add.>+1</div>" tmp
+	grep ">diff --git a/file-1 b/file-1" tmp &&
+	grep "<span class=.add.>+1</span>" tmp
 '
 
 test_done
diff --git a/tests/t0106-diff.sh b/www/git.causal.agency/cgit/tests/t0106-diff.sh
index 82b645ec..62a0a74a 100755
--- a/tests/t0106-diff.sh
+++ b/www/git.causal.agency/cgit/tests/t0106-diff.sh
@@ -9,11 +9,11 @@ test_expect_success 'find blob link' 'grep "<a href=./foo/tree/file-5?id=" tmp'
 test_expect_success 'find added file' 'grep "new file mode 100644" tmp'
 
 test_expect_success 'find hunk header' '
-	grep "<div class=.hunk.>@@ -0,0 +1 @@</div>" tmp
+	grep "<span class=.hunk.>@@ -0,0 +1 @@</span>" tmp
 '
 
 test_expect_success 'find added line' '
-	grep "<div class=.add.>+5</div>" tmp
+	grep "<span class=.add.>+5</span>" tmp
 '
 
 test_done
diff --git a/tests/t0107-snapshot.sh b/www/git.causal.agency/cgit/tests/t0107-snapshot.sh
index 0811ec40..0811ec40 100755
--- a/tests/t0107-snapshot.sh
+++ b/www/git.causal.agency/cgit/tests/t0107-snapshot.sh
diff --git a/tests/t0108-patch.sh b/www/git.causal.agency/cgit/tests/t0108-patch.sh
index 013d6802..013d6802 100755
--- a/tests/t0108-patch.sh
+++ b/www/git.causal.agency/cgit/tests/t0108-patch.sh
diff --git a/tests/t0109-gitconfig.sh b/www/git.causal.agency/cgit/tests/t0109-gitconfig.sh
index 189ef281..189ef281 100755
--- a/tests/t0109-gitconfig.sh
+++ b/www/git.causal.agency/cgit/tests/t0109-gitconfig.sh
diff --git a/tests/t0110-rawdiff.sh b/www/git.causal.agency/cgit/tests/t0110-rawdiff.sh
index 66fa7d5d..66fa7d5d 100755
--- a/tests/t0110-rawdiff.sh
+++ b/www/git.causal.agency/cgit/tests/t0110-rawdiff.sh
diff --git a/tests/t0111-filter.sh b/www/git.causal.agency/cgit/tests/t0111-filter.sh
index 2fdc3669..e5d35750 100755
--- a/tests/t0111-filter.sh
+++ b/www/git.causal.agency/cgit/tests/t0111-filter.sh
@@ -4,9 +4,6 @@ test_description='Check filtered content'
 . ./setup.sh
 
 prefixes="exec"
-if [ $CGIT_HAS_LUA -eq 1 ]; then
-	prefixes="$prefixes lua"
-fi
 
 for prefix in $prefixes
 do
diff --git a/tests/valgrind/bin/cgit b/www/git.causal.agency/cgit/tests/valgrind/bin/cgit
index dcdfbe53..dcdfbe53 100755
--- a/tests/valgrind/bin/cgit
+++ b/www/git.causal.agency/cgit/tests/valgrind/bin/cgit
diff --git a/ui-atom.c b/www/git.causal.agency/cgit/ui-atom.c
index 1056f363..1056f363 100644
--- a/ui-atom.c
+++ b/www/git.causal.agency/cgit/ui-atom.c
diff --git a/ui-atom.h b/www/git.causal.agency/cgit/ui-atom.h
index dda953bb..dda953bb 100644
--- a/ui-atom.h
+++ b/www/git.causal.agency/cgit/ui-atom.h
diff --git a/ui-blame.c b/www/git.causal.agency/cgit/ui-blame.c
index 03136f78..4adec2b9 100644
--- a/ui-blame.c
+++ b/www/git.causal.agency/cgit/ui-blame.c
@@ -152,6 +152,10 @@ static void print_object(const struct object_id *oid, const char *path,
 	cgit_tree_link("tree", NULL, NULL, ctx.qry.head, rev, path);
 	html(")\n");
 
+	if (buffer_is_binary(buf, size)) {
+		html("<div class='error'>blob is binary.</div>");
+		goto cleanup;
+	}
 	if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) {
 		htmlf("<div class='error'>blob size (%ldKB)"
 		      " exceeds display size limit (%dKB).</div>",
diff --git a/ui-blame.h b/www/git.causal.agency/cgit/ui-blame.h
index 5b97e035..5b97e035 100644
--- a/ui-blame.h
+++ b/www/git.causal.agency/cgit/ui-blame.h
diff --git a/ui-blob.c b/www/git.causal.agency/cgit/ui-blob.c
index c10ae42e..c10ae42e 100644
--- a/ui-blob.c
+++ b/www/git.causal.agency/cgit/ui-blob.c
diff --git a/ui-blob.h b/www/git.causal.agency/cgit/ui-blob.h
index 16847b20..16847b20 100644
--- a/ui-blob.h
+++ b/www/git.causal.agency/cgit/ui-blob.h
diff --git a/ui-clone.c b/www/git.causal.agency/cgit/ui-clone.c
index 5dccb639..5dccb639 100644
--- a/ui-clone.c
+++ b/www/git.causal.agency/cgit/ui-clone.c
diff --git a/ui-clone.h b/www/git.causal.agency/cgit/ui-clone.h
index 3e460a3d..3e460a3d 100644
--- a/ui-clone.h
+++ b/www/git.causal.agency/cgit/ui-clone.h
diff --git a/ui-commit.c b/www/git.causal.agency/cgit/ui-commit.c
index 948118c4..b49259e6 100644
--- a/ui-commit.c
+++ b/www/git.causal.agency/cgit/ui-commit.c
@@ -39,10 +39,11 @@ void cgit_print_commit(char *hex, const char *prefix)
 	}
 	info = cgit_parse_commit(commit);
 
-	format_display_notes(&oid, &notes, PAGE_ENCODING, 0);
+	format_display_notes(&oid, &notes, PAGE_ENCODING, 1);
 
 	load_ref_decorations(NULL, DECORATE_FULL_REFS);
 
+	ctx.page.title = fmtalloc("%s - %s", info->subject, ctx.page.title);
 	cgit_print_layout_start();
 	cgit_print_diff_ctrls();
 	html("<table summary='commit info' class='commit-info'>\n");
@@ -120,11 +121,11 @@ void cgit_print_commit(char *hex, const char *prefix)
 	cgit_close_filter(ctx.repo->commit_filter);
 	show_commit_decorations(commit);
 	html("</div>");
-	html("<div class='commit-msg'>");
+	html("<pre class='commit-msg'>");
 	cgit_open_filter(ctx.repo->commit_filter);
 	html_txt(info->msg);
 	cgit_close_filter(ctx.repo->commit_filter);
-	html("</div>");
+	html("</pre>");
 	if (notes.len != 0) {
 		html("<div class='notes-header'>Notes</div>");
 		html("<div class='notes'>");
diff --git a/ui-commit.h b/www/git.causal.agency/cgit/ui-commit.h
index 8198b4ba..8198b4ba 100644
--- a/ui-commit.h
+++ b/www/git.causal.agency/cgit/ui-commit.h
diff --git a/ui-diff.c b/www/git.causal.agency/cgit/ui-diff.c
index 5ed5990c..2a64ae8f 100644
--- a/ui-diff.c
+++ b/www/git.causal.agency/cgit/ui-diff.c
@@ -231,11 +231,11 @@ static void print_line(char *line, int len)
 	else if (line[0] == '@')
 		class = "hunk";
 
-	htmlf("<div class='%s'>", class);
+	htmlf("<span class='%s'>", class);
 	line[len-1] = '\0';
 	html_txt(line);
-	html("</div>");
 	line[len-1] = c;
+	html("</span>\n");
 }
 
 static void header(const struct object_id *oid1, char *path1, int mode1,
@@ -245,22 +245,23 @@ static void header(const struct object_id *oid1, char *path1, int mode1,
 	int subproject;
 
 	subproject = (S_ISGITLINK(mode1) || S_ISGITLINK(mode2));
-	html("<div class='head'>");
+	html("<span class='head'>");
 	html("diff --git a/");
 	html_txt(path1);
 	html(" b/");
 	html_txt(path2);
+	html("\n");
 
 	if (mode1 == 0)
-		htmlf("<br/>new file mode %.6o", mode2);
+		htmlf("new file mode %.6o\n", mode2);
 
 	if (mode2 == 0)
-		htmlf("<br/>deleted file mode %.6o", mode1);
+		htmlf("deleted file mode %.6o\n", mode1);
 
 	if (!subproject) {
 		abbrev1 = xstrdup(find_unique_abbrev(oid1, DEFAULT_ABBREV));
 		abbrev2 = xstrdup(find_unique_abbrev(oid2, DEFAULT_ABBREV));
-		htmlf("<br/>index %s..%s", abbrev1, abbrev2);
+		htmlf("index %s..%s", abbrev1, abbrev2);
 		free(abbrev1);
 		free(abbrev2);
 		if (mode1 != 0 && mode2 != 0) {
@@ -268,28 +269,31 @@ static void header(const struct object_id *oid1, char *path1, int mode1,
 			if (mode2 != mode1)
 				htmlf("..%.6o", mode2);
 		}
+		html("\n");
 		if (is_null_oid(oid1)) {
 			path1 = "dev/null";
-			html("<br/>--- /");
+			html("--- /");
 		} else
-			html("<br/>--- a/");
+			html("--- a/");
 		if (mode1 != 0)
 			cgit_tree_link(path1, NULL, NULL, ctx.qry.head,
 				       oid_to_hex(old_rev_oid), path1);
 		else
 			html_txt(path1);
+		html("\n");
 		if (is_null_oid(oid2)) {
 			path2 = "dev/null";
-			html("<br/>+++ /");
+			html("+++ /");
 		} else
-			html("<br/>+++ b/");
+			html("+++ b/");
 		if (mode2 != 0)
 			cgit_tree_link(path2, NULL, NULL, ctx.qry.head,
 				       oid_to_hex(new_rev_oid), path2);
 		else
 			html_txt(path2);
+		html("\n");
 	}
-	html("</div>");
+	html("</span>");
 }
 
 static void filepair_cb(struct diff_filepair *pair)
@@ -488,12 +492,12 @@ void cgit_print_diff(const char *new_rev, const char *old_rev,
 		html("<table summary='ssdiff' class='ssdiff'>");
 	} else {
 		html("<table summary='diff' class='diff'>");
-		html("<tr><td>");
+		html("<tr><td><pre>");
 	}
 	cgit_diff_tree(old_rev_oid, new_rev_oid, filepair_cb, prefix,
 		       ctx.qry.ignorews);
 	if (!use_ssdiff)
-		html("</td></tr>");
+		html("</pre></td></tr>");
 	html("</table>");
 
 	if (show_ctrls)
diff --git a/ui-diff.h b/www/git.causal.agency/cgit/ui-diff.h
index 39264a16..39264a16 100644
--- a/ui-diff.h
+++ b/www/git.causal.agency/cgit/ui-diff.h
diff --git a/ui-log.c b/www/git.causal.agency/cgit/ui-log.c
index 20774bf8..b443ca73 100644
--- a/ui-log.c
+++ b/www/git.causal.agency/cgit/ui-log.c
@@ -75,11 +75,13 @@ void show_commit_decorations(struct commit *commit)
 			 * don't display anything. */
 			break;
 		case DECORATION_REF_LOCAL:
+			html(" ");
 			cgit_log_link(buf, NULL, "branch-deco", buf, NULL,
 				ctx.qry.vpath, 0, NULL, NULL,
 				ctx.qry.showmsg, 0);
 			break;
 		case DECORATION_REF_TAG:
+			html(" ");
 			if (!read_ref(deco->name, &oid_tag) && !peel_iterated_oid(&oid_tag, &peeled))
 				is_annotated = !oideq(&oid_tag, &peeled);
 			cgit_tag_link(buf, NULL, is_annotated ? "tag-annotated-deco" : "tag-deco", buf);
@@ -87,12 +89,14 @@ void show_commit_decorations(struct commit *commit)
 		case DECORATION_REF_REMOTE:
 			if (!ctx.repo->enable_remote_branches)
 				break;
+			html(" ");
 			cgit_log_link(buf, NULL, "remote-deco", NULL,
 				oid_to_hex(&commit->object.oid),
 				ctx.qry.vpath, 0, NULL, NULL,
 				ctx.qry.showmsg, 0);
 			break;
 		default:
+			html(" ");
 			cgit_commit_link(buf, NULL, "deco", ctx.qry.head,
 					oid_to_hex(&commit->object.oid),
 					ctx.qry.vpath);
diff --git a/ui-log.h b/www/git.causal.agency/cgit/ui-log.h
index 325607cd..325607cd 100644
--- a/ui-log.h
+++ b/www/git.causal.agency/cgit/ui-log.h
diff --git a/ui-patch.c b/www/git.causal.agency/cgit/ui-patch.c
index 4ac03cbe..4ac03cbe 100644
--- a/ui-patch.c
+++ b/www/git.causal.agency/cgit/ui-patch.c
diff --git a/ui-patch.h b/www/git.causal.agency/cgit/ui-patch.h
index 7a6cacd5..7a6cacd5 100644
--- a/ui-patch.h
+++ b/www/git.causal.agency/cgit/ui-patch.h
diff --git a/ui-plain.c b/www/git.causal.agency/cgit/ui-plain.c
index 65a205fa..65a205fa 100644
--- a/ui-plain.c
+++ b/www/git.causal.agency/cgit/ui-plain.c
diff --git a/ui-plain.h b/www/git.causal.agency/cgit/ui-plain.h
index 5bff07b8..5bff07b8 100644
--- a/ui-plain.h
+++ b/www/git.causal.agency/cgit/ui-plain.h
diff --git a/ui-refs.c b/www/git.causal.agency/cgit/ui-refs.c
index 456f610d..456f610d 100644
--- a/ui-refs.c
+++ b/www/git.causal.agency/cgit/ui-refs.c
diff --git a/ui-refs.h b/www/git.causal.agency/cgit/ui-refs.h
index 1d4a54a2..1d4a54a2 100644
--- a/ui-refs.h
+++ b/www/git.causal.agency/cgit/ui-refs.h
diff --git a/ui-repolist.c b/www/git.causal.agency/cgit/ui-repolist.c
index 529a2038..97b11c5f 100644
--- a/ui-repolist.c
+++ b/www/git.causal.agency/cgit/ui-repolist.c
@@ -321,7 +321,7 @@ void cgit_print_repolist(void)
 		}
 		htmlf("<tr><td class='%s'>",
 		      !sorted && section ? "sublevel-repo" : "toplevel-repo");
-		cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL);
+		cgit_summary_link(ctx.repo->name, NULL, NULL, NULL);
 		html("</td><td>");
 		repourl = cgit_repourl(ctx.repo->url);
 		html_link_open(repourl, NULL, NULL);
@@ -353,8 +353,10 @@ void cgit_print_repolist(void)
 		if (ctx.cfg.enable_index_links) {
 			html("<td>");
 			cgit_summary_link("summary", NULL, "button", NULL);
+			html(" ");
 			cgit_log_link("log", NULL, "button", NULL, NULL, NULL,
 				      0, NULL, NULL, ctx.qry.showmsg, 0);
+			html(" ");
 			cgit_tree_link("tree", NULL, "button", NULL, NULL, NULL);
 			html("</td>");
 		}
diff --git a/ui-repolist.h b/www/git.causal.agency/cgit/ui-repolist.h
index 1b6b3227..1b6b3227 100644
--- a/ui-repolist.h
+++ b/www/git.causal.agency/cgit/ui-repolist.h
diff --git a/ui-shared.c b/www/git.causal.agency/cgit/ui-shared.c
index acd8ab55..dfaf5952 100644
--- a/ui-shared.c
+++ b/www/git.causal.agency/cgit/ui-shared.c
@@ -835,7 +835,7 @@ void cgit_print_docend(void)
 	if (ctx.cfg.footer)
 		html_include(ctx.cfg.footer);
 	else {
-		htmlf("<div class='footer'>generated by <a href='https://git.zx2c4.com/cgit/about/'>cgit %s</a> "
+		htmlf("<div class='footer'>generated by <a href='https://git.causal.agency/src/log/www/git.causal.agency/cgit'>cgit %s</a> "
 			"(<a href='https://git-scm.com/'>git %s</a>) at ", cgit_version, git_version_string);
 		html_txt(show_date(time(NULL), 0, cgit_date_mode(DATE_ISO8601)));
 		html("</div>\n");
@@ -894,6 +894,15 @@ void cgit_add_clone_urls(void (*fn)(const char *))
 		add_clone_urls(fn, ctx.cfg.clone_prefix, ctx.repo->url);
 }
 
+static int print_this_commit_option(void)
+{
+	struct object_id oid;
+	if (!ctx.qry.head || get_oid(ctx.qry.head, &oid))
+		return 1;
+	html_option(oid_to_hex(&oid), "this commit", ctx.qry.head);
+	return 0;
+}
+
 static int print_branch_option(const char *refname, const struct object_id *oid,
 			       int flags, void *cb_data)
 {
@@ -995,15 +1004,18 @@ static void print_header(void)
 	if (ctx.repo) {
 		cgit_index_link("index", NULL, NULL, NULL, NULL, 0, 1);
 		html(" : ");
-		cgit_summary_link(ctx.repo->name, ctx.repo->name, NULL, NULL);
+		cgit_summary_link(ctx.repo->name, NULL, NULL, NULL);
 		if (ctx.env.authenticated) {
 			html("</td><td class='form'>");
 			html("<form method='get'>\n");
 			cgit_add_hidden_formfields(0, 1, ctx.qry.page);
 			html("<select name='h' onchange='this.form.submit();'>\n");
+			print_this_commit_option();
+			html("<optgroup label='branches'>");
 			for_each_branch_ref(print_branch_option, ctx.qry.head);
 			if (ctx.repo->enable_remote_branches)
 				for_each_remote_ref(print_branch_option, ctx.qry.head);
+			html("</optgroup>");
 			html("</select> ");
 			html("<input type='submit' value='switch'/>");
 			html("</form>");
@@ -1016,7 +1028,13 @@ static void print_header(void)
 	if (ctx.repo) {
 		html_txt(ctx.repo->desc);
 		html("</td><td class='sub right'>");
-		html_txt(ctx.repo->owner);
+		if (ctx.repo->owner_filter) {
+			cgit_open_filter(ctx.repo->owner_filter);
+			html_txt(ctx.repo->owner);
+			cgit_close_filter(ctx.repo->owner_filter);
+		} else {
+			html_txt(ctx.repo->owner);
+		}
 	} else {
 		if (ctx.cfg.root_desc)
 			html_txt(ctx.cfg.root_desc);
@@ -1032,32 +1050,41 @@ void cgit_print_pageheader(void)
 
 	html("<table class='tabs'><tr><td>\n");
 	if (ctx.env.authenticated && ctx.repo) {
-		if (ctx.repo->readme.nr)
+		if (ctx.repo->readme.nr) {
 			reporevlink("about", "about", NULL,
 				    hc("about"), ctx.qry.head, NULL,
 				    NULL);
+			html(" ");
+		}
 		cgit_summary_link("summary", NULL, hc("summary"),
 				  ctx.qry.head);
+		html(" ");
 		cgit_refs_link("refs", NULL, hc("refs"), ctx.qry.head,
 			       ctx.qry.oid, NULL);
+		html(" ");
 		cgit_log_link("log", NULL, hc("log"), ctx.qry.head,
 			      NULL, ctx.qry.vpath, 0, NULL, NULL,
 			      ctx.qry.showmsg, ctx.qry.follow);
+		html(" ");
 		if (ctx.qry.page && !strcmp(ctx.qry.page, "blame"))
 			cgit_blame_link("blame", NULL, hc("blame"), ctx.qry.head,
 				        ctx.qry.oid, ctx.qry.vpath);
 		else
 			cgit_tree_link("tree", NULL, hc("tree"), ctx.qry.head,
 				       ctx.qry.oid, ctx.qry.vpath);
+		html(" ");
 		cgit_commit_link("commit", NULL, hc("commit"),
 				 ctx.qry.head, ctx.qry.oid, ctx.qry.vpath);
+		html(" ");
 		cgit_diff_link("diff", NULL, hc("diff"), ctx.qry.head,
 			       ctx.qry.oid, ctx.qry.oid2, ctx.qry.vpath);
-		if (ctx.repo->max_stats)
+		if (ctx.repo->max_stats) {
+			html(" ");
 			cgit_stats_link("stats", NULL, hc("stats"),
 					ctx.qry.head, ctx.qry.vpath);
+		}
 		if (ctx.repo->homepage) {
-			html("<a href='");
+			html(" <a href='");
 			html_attr(ctx.repo->homepage);
 			html("'>homepage</a>");
 		}
@@ -1201,9 +1228,12 @@ void cgit_set_title_from_path(const char *path)
 	if (!path)
 		return;
 
-	for (last_slash = path + strlen(path); (slash = memrchr(path, '/', last_slash - path)) != NULL; last_slash = slash) {
+	last_slash = path + strlen(path);
+	for (slash = last_slash; slash > path; --slash) {
+		if (*slash != '/') continue;
 		strbuf_add(&sb, slash + 1, last_slash - slash - 1);
 		strbuf_addstr(&sb, " \xc2\xab ");
+		last_slash = slash;
 	}
 	strbuf_add(&sb, path, last_slash - path);
 	strbuf_addf(&sb, " - %s", ctx.page.title);
diff --git a/ui-shared.h b/www/git.causal.agency/cgit/ui-shared.h
index 6964873a..6964873a 100644
--- a/ui-shared.h
+++ b/www/git.causal.agency/cgit/ui-shared.h
diff --git a/ui-snapshot.c b/www/git.causal.agency/cgit/ui-snapshot.c
index 18361a65..28013935 100644
--- a/ui-snapshot.c
+++ b/www/git.causal.agency/cgit/ui-snapshot.c
@@ -37,6 +37,9 @@ static int write_archive_type(const char *format, const char *hex, const char *p
 	/* strvec guarantees a trailing NULL entry. */
 	memcpy(nargv, argv.v, sizeof(char *) * (argv.nr + 1));
 
+	if (fflush(stdout))
+		return errno;
+
 	result = write_archive(argv.nr, nargv, NULL, the_repository, NULL, 0);
 	strvec_clear(&argv);
 	free(nargv);
diff --git a/ui-snapshot.h b/www/git.causal.agency/cgit/ui-snapshot.h
index a8deec36..a8deec36 100644
--- a/ui-snapshot.h
+++ b/www/git.causal.agency/cgit/ui-snapshot.h
diff --git a/ui-ssdiff.c b/www/git.causal.agency/cgit/ui-ssdiff.c
index af8bc9e0..af8bc9e0 100644
--- a/ui-ssdiff.c
+++ b/www/git.causal.agency/cgit/ui-ssdiff.c
diff --git a/ui-ssdiff.h b/www/git.causal.agency/cgit/ui-ssdiff.h
index 11f27144..11f27144 100644
--- a/ui-ssdiff.h
+++ b/www/git.causal.agency/cgit/ui-ssdiff.h
diff --git a/ui-stats.c b/www/git.causal.agency/cgit/ui-stats.c
index 09b3625e..09b3625e 100644
--- a/ui-stats.c
+++ b/www/git.causal.agency/cgit/ui-stats.c
diff --git a/ui-stats.h b/www/git.causal.agency/cgit/ui-stats.h
index 0e61b03d..0e61b03d 100644
--- a/ui-stats.h
+++ b/www/git.causal.agency/cgit/ui-stats.h
diff --git a/ui-summary.c b/www/git.causal.agency/cgit/ui-summary.c
index 947812a8..947812a8 100644
--- a/ui-summary.c
+++ b/www/git.causal.agency/cgit/ui-summary.c
diff --git a/ui-summary.h b/www/git.causal.agency/cgit/ui-summary.h
index cba696af..cba696af 100644
--- a/ui-summary.h
+++ b/www/git.causal.agency/cgit/ui-summary.h
diff --git a/ui-tag.c b/www/git.causal.agency/cgit/ui-tag.c
index 424bbccd..05952429 100644
--- a/ui-tag.c
+++ b/www/git.causal.agency/cgit/ui-tag.c
@@ -25,9 +25,9 @@ static void print_tag_content(char *buf)
 	html_txt(buf);
 	html("</div>");
 	if (p) {
-		html("<div class='commit-msg'>");
+		html("<pre class='commit-msg'>");
 		html_txt(++p);
-		html("</div>");
+		html("</pre>");
 	}
 }
 
diff --git a/ui-tag.h b/www/git.causal.agency/cgit/ui-tag.h
index d295cdcd..d295cdcd 100644
--- a/ui-tag.h
+++ b/www/git.causal.agency/cgit/ui-tag.h
diff --git a/ui-tree.c b/www/git.causal.agency/cgit/ui-tree.c
index b61f6f54..21e0b884 100644
--- a/ui-tree.c
+++ b/www/git.causal.agency/cgit/ui-tree.c
@@ -89,6 +89,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch
 	enum object_type type;
 	char *buf;
 	unsigned long size;
+	int is_binary;
 
 	type = oid_object_info(the_repository, oid, &size);
 	if (type == OBJ_BAD) {
@@ -103,6 +104,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch
 			"Error reading object %s", oid_to_hex(oid));
 		return;
 	}
+	is_binary = buffer_is_binary(buf, size);
 
 	cgit_set_title_from_path(path);
 
@@ -110,7 +112,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch
 	htmlf("blob: %s (", oid_to_hex(oid));
 	cgit_plain_link("plain", NULL, NULL, ctx.qry.head,
 		        rev, path);
-	if (ctx.repo->enable_blame) {
+	if (ctx.repo->enable_blame && !is_binary) {
 		html(") (");
 		cgit_blame_link("blame", NULL, NULL, ctx.qry.head,
 			        rev, path);
@@ -123,7 +125,7 @@ static void print_object(const struct object_id *oid, const char *path, const ch
 		return;
 	}
 
-	if (buffer_is_binary(buf, size))
+	if (is_binary)
 		print_binary_buffer(buf, size);
 	else
 		print_text_buffer(basename, buf, size);
@@ -202,9 +204,11 @@ static int ls_item(const struct object_id *oid, struct strbuf *base,
 	struct walk_tree_context *walk_tree_ctx = cbdata;
 	char *name;
 	struct strbuf fullpath = STRBUF_INIT;
+	struct strbuf linkpath = STRBUF_INIT;
 	struct strbuf class = STRBUF_INIT;
 	enum object_type type;
 	unsigned long size = 0;
+	char *buf;
 
 	name = xstrdup(pathname);
 	strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "",
@@ -216,8 +220,7 @@ static int ls_item(const struct object_id *oid, struct strbuf *base,
 			htmlf("<tr><td colspan='3'>Bad object: %s %s</td></tr>",
 			      name,
 			      oid_to_hex(oid));
-			free(name);
-			return 0;
+			goto cleanup;
 		}
 	}
 
@@ -237,22 +240,45 @@ static int ls_item(const struct object_id *oid, struct strbuf *base,
 		cgit_tree_link(name, NULL, class.buf, ctx.qry.head,
 			       walk_tree_ctx->curr_rev, fullpath.buf);
 	}
+	if (S_ISLNK(mode)) {
+		html(" -> ");
+		buf = read_object_file(oid, &type, &size);
+		if (!buf) {
+			htmlf("Error reading object: %s", oid_to_hex(oid));
+			goto cleanup;
+		}
+		strbuf_addbuf(&linkpath, &fullpath);
+		strbuf_addf(&linkpath, "/../%s", buf);
+		strbuf_normalize_path(&linkpath);
+		cgit_tree_link(buf, NULL, class.buf, ctx.qry.head,
+			walk_tree_ctx->curr_rev, linkpath.buf);
+		free(buf);
+		strbuf_release(&linkpath);
+	}
 	htmlf("</td><td class='ls-size'>%li</td>", size);
 
 	html("<td>");
 	cgit_log_link("log", NULL, "button", ctx.qry.head,
 		      walk_tree_ctx->curr_rev, fullpath.buf, 0, NULL, NULL,
 		      ctx.qry.showmsg, 0);
-	if (ctx.repo->max_stats)
+	if (ctx.repo->max_stats) {
+		html(" ");
 		cgit_stats_link("stats", NULL, "button", ctx.qry.head,
 				fullpath.buf);
-	if (!S_ISGITLINK(mode))
+	}
+	if (!S_ISGITLINK(mode)) {
+		html(" ");
 		cgit_plain_link("plain", NULL, "button", ctx.qry.head,
 				walk_tree_ctx->curr_rev, fullpath.buf);
-	if (!S_ISDIR(mode) && ctx.repo->enable_blame)
+	}
+	if (!S_ISDIR(mode) && ctx.repo->enable_blame) {
+		html(" ");
 		cgit_blame_link("blame", NULL, "button", ctx.qry.head,
 				walk_tree_ctx->curr_rev, fullpath.buf);
+	}
 	html("</td></tr>\n");
+
+cleanup:
 	free(name);
 	strbuf_release(&fullpath);
 	strbuf_release(&class);
diff --git a/ui-tree.h b/www/git.causal.agency/cgit/ui-tree.h
index bbd34e35..bbd34e35 100644
--- a/ui-tree.h
+++ b/www/git.causal.agency/cgit/ui-tree.h
diff --git a/www/git.causal.agency/cgitrc b/www/git.causal.agency/cgitrc
new file mode 100644
index 00000000..8ccd7c72
--- /dev/null
+++ b/www/git.causal.agency/cgitrc
@@ -0,0 +1,29 @@
+root-title=causal agency
+root-desc=“I think some people from the Gentoo project are behind this.â€
+logo=
+
+clone-url=https://$HTTP_HOST/$CGIT_REPO_URL
+snapshots=tar.gz zip
+
+enable-blame=1
+enable-commit-graph=1
+enable-subject-links=1
+enable-follow-links=1
+enable-index-owner=0
+repository-sort=age
+branch-sort=age
+
+css=/custom.css
+email-filter=/usr/local/libexec/cgit-email
+about-filter=/usr/local/libexec/about-filter
+source-filter=/usr/local/libexec/source-filter
+owner-filter=/usr/local/libexec/owner-filter
+
+readme=:README.7
+readme=:README
+
+remove-suffix=1
+enable-git-config=1
+scan-path=/home/june/pub
+
+cache-size=1024
diff --git a/www/git.causal.agency/custom.css b/www/git.causal.agency/custom.css
new file mode 100644
index 00000000..3bc61c90
--- /dev/null
+++ b/www/git.causal.agency/custom.css
@@ -0,0 +1,86 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+@import url("cgit.css");
+
+* { line-height: 1.25em; }
+
+div#cgit {
+	max-width: 117ch;
+	margin: auto;
+	font-family: monospace;
+	-moz-tab-size: 4;
+	tab-size: 4;
+}
+
+div#cgit table#header td.sub {
+	border-top: none;
+}
+div#cgit table#header td.sub.right {
+	padding-right: 1em;
+}
+div#cgit table.tabs {
+	border-bottom: none;
+}
+div#cgit div.content {
+	border-bottom: none;
+}
+div#cgit table.list th a {
+	color: inherit;
+}
+div#cgit table.list tr:nth-child(even) {
+	background: inherit;
+}
+div#cgit table.list tr:hover {
+	background: inherit;
+}
+div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
+	background: inherit;
+}
+
+div#cgit table.blob td.linenumbers a:target {
+	color: goldenrod;
+	text-decoration: underline;
+	outline: none;
+}
+
+div#cgit div#summary {
+	max-width: 80ch;
+}
+
+/* for hilex(1) */
+div#cgit pre .Ke { color: dimgray; }
+div#cgit pre .Ma { color: green; }
+div#cgit pre .Co { color: navy; }
+div#cgit pre .St { color: teal; }
+div#cgit pre .Fo { color: teal; font-weight: bold; }
+div#cgit pre .Su { color: olive; }
+
+/* for htagml(1) */
+div#cgit pre a.tag { color: inherit; text-decoration: underline; }
+div#cgit pre a.tag:target { color: goldenrod; outline: none; }
+
+/* for mandoc(1) */
+table.head, table.foot { width: 100%; }
+td.head-rtitle, td.foot-os { text-align: right; }
+td.head-vol { text-align: center; }
+div.Pp { margin: 1ex 0ex; }
+div.Nd, div.Bf, div.Op { display: inline; }
+span.Pa, span.Ad { font-style: italic; }
+span.Ms { font-weight: bold; }
+dl.Bl-diag > dt { font-weight: bold; }
+code.Nm, code.Fl, code.Cm, code.Ic, code.In, code.Fd, code.Fn,
+code.Cd { font-weight: bold; font-family: inherit; }
+
+h1.Sh { font-size: 1.5em; }
+table.Nm td:first-child { padding-right: 1ch; }
+code.Fl { white-space: nowrap; }
+span.RsT { font-style: italic; }
+dl.Bl-tag:not(.Bl-compact) dt { margin-top: 1em; }
+ul.Bl-bullet:not(.Bl-compact) li { margin-top: 1em; }
+div.Bd-indent { margin-left: 4ch; }
+table.Bl-column { width: 100%; }
+table.foot { margin-top: 1em; }
+
+div#cgit a.permalink { color: inherit; }
diff --git a/www/git.causal.agency/owner-filter.sh b/www/git.causal.agency/owner-filter.sh
new file mode 100644
index 00000000..18e74cf1
--- /dev/null
+++ b/www/git.causal.agency/owner-filter.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -eu
+
+cat <<EOF
+<a href="https://liberapay.com/june/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
+EOF
diff --git a/www/git.causal.agency/source-filter.sh b/www/git.causal.agency/source-filter.sh
new file mode 100644
index 00000000..514272db
--- /dev/null
+++ b/www/git.causal.agency/source-filter.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+set -eu
+
+ctags=/usr/bin/ctags
+mtags=/usr/local/libexec/mtags
+hilex=/usr/local/libexec/hilex
+htagml=/usr/local/libexec/htagml
+
+case "$1" in
+	(*.[chlmy]|Makefile|*.mk|*.[1-9]|.profile|.shrc|*.sh)
+		tmp=$(mktemp -d -t source-filter)
+		trap 'rm -fr "${tmp}"' EXIT
+		cd "${tmp}"
+		cat >"$1"
+		touch tags
+		case "$1" in
+			(*.[chlmy]) $ctags -w "$1";;
+			(*) $mtags "$1";;
+		esac
+		$hilex -f html "$1" | $htagml -i "$1"
+		;;
+	(*)
+		exec $hilex -t -n "$1" -f html
+		;;
+esac
diff --git a/www/temp.causal.agency/.gitignore b/www/temp.causal.agency/.gitignore
new file mode 100644
index 00000000..e31ee94e
--- /dev/null
+++ b/www/temp.causal.agency/.gitignore
@@ -0,0 +1 @@
+up
diff --git a/www/temp.causal.agency/Makefile b/www/temp.causal.agency/Makefile
new file mode 100644
index 00000000..3e908305
--- /dev/null
+++ b/www/temp.causal.agency/Makefile
@@ -0,0 +1,16 @@
+WEBROOT = /usr/local/www/temp.causal.agency
+
+CFLAGS += -std=c11 -Wall -Wextra -Wpedantic -I/usr/local/include
+LDFLAGS += -static -L/usr/local/lib
+LDLIBS = -lkcgihtml -lkcgi -lz -lmd
+
+up:
+
+clean:
+	rm -f up
+
+install: up
+	install -m 700 up ${WEBROOT}/up
+
+uninstall:
+	rm -f ${WEBROOT}/up
diff --git a/www/temp.causal.agency/up.c b/www/temp.causal.agency/up.c
new file mode 100644
index 00000000..9e7b4ff7
--- /dev/null
+++ b/www/temp.causal.agency/up.c
@@ -0,0 +1,156 @@
+/* Copyright (C) 2020  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/capsicum.h>
+#include <sys/types.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <kcgi.h>
+#include <kcgihtml.h>
+
+static int cwd = -1;
+
+static const struct kvalid Key = { NULL, "file" };
+
+static enum kcgi_err head(struct kreq *req, enum khttp http, enum kmime mime) {
+	return khttp_head(req, kresps[KRESP_STATUS], "%s", khttps[http])
+		|| khttp_head(req, kresps[KRESP_CONTENT_TYPE], "%s", kmimetypes[mime]);
+}
+
+static enum kcgi_err fail(struct kreq *req, enum khttp http) {
+	return head(req, http, KMIME_TEXT_PLAIN)
+		|| khttp_body(req)
+		|| khttp_printf(req, "%s\n", khttps[http]);
+}
+
+static enum kcgi_err handle(struct kreq *req) {
+	if (req->page) return fail(req, KHTTP_404);
+
+	if (req->method == KMETHOD_GET) {
+		struct khtmlreq html;
+		struct khtmlreq *h = &html;
+		return head(req, KHTTP_200, KMIME_TEXT_HTML)
+			|| khttp_body(req)
+			|| khtml_open(h, req, 0)
+			|| khtml_elem(h, KELEM_DOCTYPE)
+			|| khtml_elem(h, KELEM_TITLE)
+			|| khtml_puts(h, "Upload")
+			|| khtml_closeelem(h, 1)
+			|| khtml_attr(
+				h, KELEM_FORM,
+				KATTR_METHOD, "post",
+				KATTR_ACTION, "",
+				KATTR_ENCTYPE, "multipart/form-data",
+				KATTR__MAX
+			)
+			|| khtml_attr(
+				h, KELEM_INPUT,
+				KATTR_TYPE, "file",
+				KATTR_NAME, Key.name,
+				KATTR__MAX
+			)
+			|| khtml_attr(
+				h, KELEM_INPUT,
+				KATTR_TYPE, "submit",
+				KATTR_VALUE, "Upload",
+				KATTR__MAX
+			)
+			|| khtml_close(h);
+
+	} else if (req->method == KMETHOD_POST) {
+		struct kpair *field = req->fieldmap[0];
+		if (!field || !field->valsz) return fail(req, KHTTP_400);
+
+		char name[256];
+		const char *ext = strrchr(field->file, '.');
+		if (!ext) ext = "";
+		snprintf(
+			name, sizeof(name), "%jx%08x%s",
+			(intmax_t)time(NULL), arc4random(), ext
+		);
+
+		int fd = openat(cwd, name, O_CREAT | O_EXCL | O_WRONLY, 0644);
+		if (fd < 0) {
+			warn("openat");
+			return fail(req, KHTTP_507);
+		}
+		ssize_t len = write(fd, field->val, field->valsz);
+		int error = close(fd);
+		if (len < 0 || error) {
+			warn("write");
+			return fail(req, KHTTP_507);
+		}
+
+		return head(req, KHTTP_303, KMIME_TEXT_PLAIN)
+			|| khttp_head(req, kresps[KRESP_LOCATION], "/%s", name)
+			|| khttp_body(req)
+			|| khttp_puts(req, name);
+
+	} else {
+		return fail(req, KHTTP_405);
+	}
+}
+
+static void sandbox(void) {
+	cwd = open(".", O_DIRECTORY);
+	if (cwd < 0) err(EX_CONFIG, ".");
+
+	int error = cap_enter();
+	if (error) err(EX_OSERR, "cap_enter");
+
+	cap_rights_t rights;
+	cap_rights_init(&rights, CAP_LOOKUP, CAP_CREATE, CAP_PWRITE);
+	error = cap_rights_limit(cwd, &rights);
+	if (error) err(EX_OSERR, "cap_rights_limit");
+}
+
+int main(void) {
+	const char *page = "up";
+	if (khttp_fcgi_test()) {
+		struct kfcgi *fcgi;
+		enum kcgi_err error = khttp_fcgi_init(&fcgi, &Key, 1, &page, 1, 0);
+		if (error) errx(EX_CONFIG, "khttp_fcgi_init: %s", kcgi_strerror(error));
+		sandbox();
+		for (
+			struct kreq req;
+			KCGI_OK == (error = khttp_fcgi_parse(fcgi, &req));
+			khttp_free(&req)
+		) {
+			error = handle(&req);
+			if (error && error != KCGI_HUP) break;
+		}
+		if (error != KCGI_EXIT) {
+			errx(EX_PROTOCOL, "khttp_fcgi_parse: %s", kcgi_strerror(error));
+		}
+		khttp_fcgi_free(fcgi);
+	} else {
+		struct kreq req;
+		enum kcgi_err error = khttp_parse(&req, &Key, 1, &page, 1, 0);
+		if (error) errx(EX_PROTOCOL, "khttp_parse: %s", kcgi_strerror(error));
+		error = handle(&req);
+		if (error) errx(EX_PROTOCOL, "%s", kcgi_strerror(error));
+		khttp_free(&req);
+	}
+}
diff --git a/www/text.causal.agency/.gitignore b/www/text.causal.agency/.gitignore
new file mode 100644
index 00000000..8fe3acc9
--- /dev/null
+++ b/www/text.causal.agency/.gitignore
@@ -0,0 +1,3 @@
+*.txt
+feed.atom
+igp
diff --git a/www/text.causal.agency/001-make.7 b/www/text.causal.agency/001-make.7
new file mode 100644
index 00000000..b4805729
--- /dev/null
+++ b/www/text.causal.agency/001-make.7
@@ -0,0 +1,159 @@
+.Dd September 17, 2018
+.Dt MAKE 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Using Make
+.Nd writing less Makefile
+.
+.Sh DESCRIPTION
+Let's talk about
+.Xr make 1 .
+I think an important thing to know about
+.Xr make 1
+is that you don't need to write a
+.Pa Makefile
+to use it.
+There are default rules
+for C, C++ and probably Fortran.
+To build
+.Pa foo
+from
+.Pa foo.c ,
+just run:
+.
+.Pp
+.Dl make foo
+.
+.Pp
+The default rule for C files uses the
+.Ev CFLAGS
+variable,
+so you can set that in the environment
+to pass flags to the C compiler:
+.
+.Pp
+.Dl CFLAGS=-Wall make foo
+.
+.Pp
+It also uses
+.Ev LDLIBS
+for linking,
+so you can add libraries with:
+.
+.Pp
+.Dl LDLIBS=-lcurses make foo
+.
+.Pp
+Obviously writing this every time
+would become tedious,
+so it might be time to write a
+.Pa Makefile .
+But it really doesn't need much:
+.
+.Bd -literal -offset indent
+CFLAGS += -Wall -Wextra
+LDLIBS = -lcurses
+
+foo:
+.Ed
+.
+.Pp
+Assigning
+.Ev CFLAGS
+with
+.Ql +=
+preserves the system default
+or anything passed in the environment.
+Declaring
+.Pa foo
+as the first rule
+makes it the default when
+.Ql make
+is run without a target.
+Note that the rule doesn't need a definition;
+the default will still be used.
+.
+.Pp
+If
+.Pa foo
+is built from serveral source files,
+unfortunately a rule definition is required:
+.
+.Bd -literal -offset indent
+OBJS = foo.o bar.o baz.o
+
+foo: $(OBJS)
+	$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
+.Ed
+.
+.Pp
+This rule uses
+.Ev LDFLAGS
+for passing linker flags,
+which is what the default rule does.
+The
+.Ql $@
+variable here expands to
+.Ql foo ,
+so this rule can be copied easily
+for other binary targets.
+.
+.Pp
+If some sources depend on a header file,
+they can be automatically rebuilt
+when the header changes
+by declaring a dependency rule:
+.
+.Pp
+.Dl foo.o bar.o: foo.h
+.
+.Pp
+Note that several files can appear
+either side of the
+.Ql ":" .
+.
+.Pp
+Lastly,
+it's always nice to add a
+.Cm clean
+target:
+.
+.Bd -literal -offset indent
+clean:
+	rm -f $(OBJS) foo
+.Ed
+.
+.Pp
+I hope this helps getting started with
+.Xr make 1
+without writing too much
+.Pa Makefile !
+.
+.Sh EXAMPLES
+The example
+.Pa Makefile
+in its entirety:
+.
+.Bd -literal -offset indent
+CFLAGS += -Wall -Wextra
+LDLIBS = -lcurses
+OBJS = foo.o bar.o baz.o
+
+foo: $(OBJS)
+	$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
+
+foo.o bar.o: foo.h
+
+clean:
+	rm -f $(OBJS) foo
+.Ed
+.
+.Sh AUTHORS
+.An Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://git.causal.agency/src/tree/www/text.causal.agency
diff --git a/www/text.causal.agency/002-writing-mdoc.7 b/www/text.causal.agency/002-writing-mdoc.7
new file mode 100644
index 00000000..b377d364
--- /dev/null
+++ b/www/text.causal.agency/002-writing-mdoc.7
@@ -0,0 +1,138 @@
+.Dd September 27, 2018
+.Dt WRITING-MDOC 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Writing mdoc
+.Nd semantic markup
+.
+.Sh DESCRIPTION
+I recently learned how to write man pages
+so that I could document
+a bunch of little programs I've written.
+Modern man pages are written in
+.Xr mdoc 7 ,
+whose documentation is also available from
+.Lk http://mandoc.bsd.lv .
+.
+.Pp
+.Xr mdoc 7
+differs from many other markup languages
+by providing
+.Dq semantic markup
+rather than just
+.Dq physical markup.
+What this means is that
+the markup indicates what something is,
+not how to format it.
+For example,
+the
+.Ql \&Ar
+macro is used to indicate
+command-line arguments
+rather than one of the macros
+for bold, italic or underline.
+This frees each author of having to choose
+and enables consistent presentation
+across different man pages.
+.
+.Pp
+Another advantage of semantic markup
+is that information can be extracted from it.
+For example,
+.Xr makewhatis 8
+can easily extract the name and short description
+from each man page
+thanks to the
+.Ql \&Nm
+and
+.Ql \&Nd
+macros.
+I use the same information
+to generate an Atom feed for these documents,
+though in admittedly a much less robust way than
+.Xr mandoc 1 .
+.
+.Pp
+When it comes to actually writing
+.Xr mdoc 7 ,
+it can take some getting used to.
+The language is of
+.Xr roff 7
+lineage
+so its syntax is very particular.
+Macros cannot appear inline,
+but must start on new lines
+beginning with
+.Ql \&. .
+Sentences should likewise
+always start on a new line.
+Since I'm in the habit of writing with
+semantic line breaks,
+I actually find these requirements
+fit in well.
+.
+.Pp
+The more frustrating syntax limitation to me
+is the rule against empty lines.
+Without them,
+it can be quite difficult to edit a lengthy document.
+Thankfully,
+lines with only a
+.Ql \&.
+on them are allowed,
+but this still causes visual noise.
+To alleviate that,
+I have a
+.Xr vim 1
+syntax file for
+.Xr mdoc 7
+which conceals the lone dots:
+.
+.Bd -literal -offset indent
+if exists("b:current_syntax")
+	finish
+endif
+
+runtime! syntax/nroff.vim
+unlet! b:current_syntax
+
+setlocal sections+=ShSs
+syntax match mdocBlank /^\\.$/ conceal
+setlocal conceallevel=2
+
+let b:current_syntax = "mdoc"
+.Ed
+.
+.Pp
+It also adds the
+.Xr mdoc 7
+section header and subsection header macros to the
+.Cm sections
+option to make
+.Xr vim 1 Ap s
+.Ic {
+and
+.Ic }
+motions
+aware of them.
+.
+.Pp
+With that,
+I've found writing man pages pleasant and rewarding.
+I've started writing other documents with
+.Xr mdoc 7
+as well,
+as you can see here.
+.
+.Sh SEE ALSO
+.Lk http://rhodesmill.org/brandon/2012/one-sentence-per-line/ "Semantic Linefeeds"
+.
+.Sh AUTHORS
+.An Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://git.causal.agency/src/tree/www/text.causal.agency
diff --git a/www/text.causal.agency/003-pleasant-c.7 b/www/text.causal.agency/003-pleasant-c.7
new file mode 100644
index 00000000..16030b7e
--- /dev/null
+++ b/www/text.causal.agency/003-pleasant-c.7
@@ -0,0 +1,120 @@
+.Dd September 30, 2018
+.Dt PLEASANT-C 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Pleasant C
+.Nd it's good, actually
+.
+.Sh DESCRIPTION
+I've been writing a lot of C lately
+and actually find it very pleasant.
+I want to talk about some of its ergonomic features.
+These are C99 features unless otherwise noted.
+.
+.Ss Initializer syntax
+Struct and union initializer syntax
+is well generalized.
+Designators can be chained,
+making initializing nested structs easy,
+and all uninitialized fields are zeroed.
+.
+.Bd -literal -offset indent
+struct {
+	struct pollfd fds[2];
+} loop = {
+	.fds[0].fd = STDIN_FILENO,
+	.fds[1].fd = STDOUT_FILENO,
+	.fds[0].events = POLLIN,
+	.fds[1].events = POLLOUT,
+};
+.Ed
+.
+.Ss Variable-length arrays
+VLAs can be multi-dimensional,
+which can avoid manual stride multiplications
+needed to index a flat
+.Xr malloc 3 Ap d
+array.
+.
+.Bd -literal -offset indent
+uint8_t glyphs[len][height][width];
+fread(glyphs, height * width, len, stdin);
+.Ed
+.
+.Ss Incomplete array types
+The last field of a struct can be an
+.Dq incomplete
+array type,
+which means it doesn't have a length.
+A variable amount of space for the struct can be
+.Xr malloc 3 Ap d ,
+or the struct can be used as
+a sort of pointer with fields.
+.
+.Bd -literal -offset indent
+struct Line {
+	enum Filter type;
+	uint8_t data[];
+} *line = &png.data[1 + lineSize()];
+.Ed
+.
+.Ss Anonymous struct and union fields (C11)
+Members of structs or unions
+which are themselves structs or unions
+can be unnamed.
+In that case,
+each of the inner fields
+is treated as a member of the outer struct or union.
+This makes working with tagged unions nicer.
+.
+.Bd -literal -offset indent
+struct Message {
+	enum { Foo, Bar } type;
+	union {
+		uint8_t foo;
+		uint32_t bar;
+	};
+} msg = { .type = Foo, .foo = 0xFF };
+.Ed
+.
+.Ss Static assert (C11)
+Assertions can be made at compile time.
+Most useful for checking sizes of structs.
+.
+.Bd -literal -offset indent
+static_assert(13 == sizeof(struct PNGHeader), "PNG IHDR size");
+.Ed
+.
+.Ss Leading-break switch
+This one is just an odd style choice
+I came across that C happens to allow.
+To prevent accidental fall-through
+in switch statements,
+you can put breaks before the case labels.
+.
+.Bd -literal -offset indent
+while (0 < (opt = getopt(argc, argv, "h:w:"))) {
+	switch (opt) {
+		break; case 'h': height = optarg;
+		break; case 'w': width = optarg;
+		break; default:  return EX_USAGE;
+	}
+}
+.Ed
+.
+.Sh AUTHORS
+.An Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://git.causal.agency/src/tree/www/text.causal.agency
+.
+.Sh CAVEATS
+This isn't meant to be advice.
+It's just how I like to write C,
+and I don't
+.Dq ship
+software in C.
diff --git a/www/text.causal.agency/004-uloc.7 b/www/text.causal.agency/004-uloc.7
new file mode 100644
index 00000000..edd78d80
--- /dev/null
+++ b/www/text.causal.agency/004-uloc.7
@@ -0,0 +1,64 @@
+.Dd December 14, 2018
+.Dt ULOC 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm ULOC
+.Nd unique lines of code
+.
+.Sh DESCRIPTION
+There are many tools available
+which measure SLOC: source lines of code.
+These tools are strangely complex
+for what they intend to do,
+which is to estimate the relative sizes of projects.
+They perform some amount of parsing
+in order to discount comments in various languages,
+and for reasons unknown each format their ouput
+in some oddly encumbered way.
+.
+.Pp
+I propose a much simpler method
+of estimating relative sizes of projects:
+unique lines of code.
+ULOC can be calculated with standard tools as follows:
+.
+.Bd -literal -offset indent
+sort -u *.h *.c | wc -l
+.Ed
+.
+.Pp
+In my opinion,
+the number this produces
+should be a better estimate of
+the complexity of a project.
+Compared to SLOC,
+not only are blank lines discounted,
+but so are close-brace lines
+and other repetitive code
+such as common includes.
+On the other hand,
+ULOC counts comments,
+which require just as much maintenance
+as the code around them does,
+while avoiding inflating the result
+with license headers which appear in every file,
+for example.
+.
+.Pp
+It can also be amusing
+to read all of your code sorted alphabetically.
+.
+.Sh AUTHORS
+.An Mt june@causal.agency
+.
+.Pp
+This document is produced from
+.Xr mdoc 7
+source available from
+.Lk https://git.causal.agency/src/tree/www/text.causal.agency
+.
+.Sh CAVEATS
+Estimates such as these
+should not be used for decision making
+as if they were data.
diff --git a/www/text.causal.agency/005-testing-c.7 b/www/text.causal.agency/005-testing-c.7
new file mode 100644
index 00000000..d0c636ff
--- /dev/null
+++ b/www/text.causal.agency/005-testing-c.7
@@ -0,0 +1,73 @@
+.Dd December 21, 2018
+.Dt TESTING-C 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Testing C
+.Nd a simple unit testing setup
+.
+.Sh DESCRIPTION
+This is a simple approach
+to unit testing in C
+that I've used in a couple projects.
+At the bottom of a C file
+with some code I want to test,
+I add:
+.
+.Bd -literal -offset indent
+#ifdef TEST
+#include <assert.h>
+
+int main(void) {
+	assert(...);
+	assert(...);
+}
+
+#endif
+.Ed
+.
+.Pp
+This file normally produces a
+.Pa .o
+to be linked into the main binary.
+For testing,
+I produce separate binaries
+and run them with
+.Xr make 1 :
+.
+.Bd -literal -offset indent
+TESTS = foo.t bar.t
+
+\&.SUFFIXES: .t
+
+\&.c.t:
+	$(CC) $(CFLAGS) -DTEST $(LDFLAGS) $< $(LDLIBS) -o $@
+
+test: $(TESTS)
+	set -e; $(TESTS:%=./%;)
+.Ed
+.
+.Pp
+Note that the test binaries
+aren't linked with the rest of the code,
+so there is potential for simple stubbing or mocking.
+.
+.Pp
+To get the best output
+from C's simple
+.Xr assert 3 ,
+it's best to assert the result
+of a helper function
+which takes the expected output
+and the test input,
+rather than calling
+.Xr assert 3
+inside the helper function.
+This way,
+the message printed by the assert failure
+contains a useful line number
+and the expected output
+rather than just variable names.
+.
+.Sh AUTHORS
+.An Mt june@causal.agency
diff --git a/www/text.causal.agency/006-some-libs.7 b/www/text.causal.agency/006-some-libs.7
new file mode 100644
index 00000000..5af65404
--- /dev/null
+++ b/www/text.causal.agency/006-some-libs.7
@@ -0,0 +1,96 @@
+.Dd December 11, 2019
+.Dt SOME-LIBS 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Some Libraries
+.Nd good ones
+.
+.Sh DESCRIPTION
+This is a little list of C libraries
+I've had good experiences using.
+.
+.Bl -tag -width Ds
+.It Fl lcurl
+The library behind the
+.Xr curl 1
+command.
+It downloads or uploads things on the internet
+through a number of protocols,
+not just HTTP.
+It has an easy-to-use library API,
+appropriately named
+.Xr libcurl-easy 3 .
+I've used it to implement a
+.Lk https://causal.agency/bin/title.html "page title fetcher" .
+.
+.It Fl lcurses
+Okay so this one really isn't great.
+Its interfaces can seem archaic
+and its documentation is often poor.
+However, it gets the job done
+and is commonly available pretty much everywhere.
+Interesting to note that
+.Nx
+uses its own implementation of curses
+that is not GNU ncurses,
+unlike
+.Fx .
+.
+.It Fl ledit
+This is a BSD line editing library,
+similar to GNU readline.
+It supports right-aligned prompts,
+which I prefer for variable-length
+information in shells.
+.
+.It Fl lkcgi
+A CGI and FastCGI library
+for web applications in C.
+Don't worry,
+it isolates HTTP parsing and input validation
+from application logic
+in sandboxed processes.
+I think it's an excellent example
+of how to design an API for C.
+I used it to implement the
+.Lk https://ascii.town/explore.html "torus web viewer" .
+.
+.It Fl lsqlite3
+An embedded relational database engine.
+It's amazing what you can do with this,
+and it's super easy to use!
+My one gripe with it is that the library and SQL documentation
+are not available as
+.Xr man 1
+pages.
+I'm currently working on a project using SQLite,
+but it hasn't gotten very far yet.
+.
+.It Fl ltls
+This is a new library in LibreSSL
+which provides a much simpler interface for TLS sockets
+compared to
+.Fl lssl .
+It's much more like what you'd expect
+from other TLS socket wrappers,
+with calls like
+.Xr tls_connect 3 ,
+.Xr tls_read 3
+and
+.Xr tls_write 3 .
+I've used this for IRC clients, bouncers and bots.
+.
+.It Fl lz
+An implementation of the DEFLATE compression algorithm
+and gzip format.
+It's all documented in comments in
+.In zlib.h ,
+which isn't bad,
+but for my own use I copied the docs into
+.Lk https://code.causal.agency/june/zlib-man-pages "manual pages" .
+I've used this for decoding and encoding PNG images.
+.El
+.
+.Sh AUTHORS
+.An June Bug Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/007-cgit-setup.7 b/www/text.causal.agency/007-cgit-setup.7
new file mode 100644
index 00000000..44fb436a
--- /dev/null
+++ b/www/text.causal.agency/007-cgit-setup.7
@@ -0,0 +1,271 @@
+.Dd December 15, 2019
+.Dt CGIT-SETUP 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm cgit setup
+.Nd configuration notes
+.
+.Sh DESCRIPTION
+I just set up cgit on
+.Lk https://git.causal.agency
+to replace an instance of gitea.
+After 30 days of uptime,
+gitea had accumulated over 11 hours of CPU time
+and was using hundreds of megabytes of memory.
+cgit is much more lightweight
+and much more in line with my aesthetic.
+I'm documenting how I set it up here
+mostly to remind myself in the future.
+.
+.Ss slowcgi
+cgit is CGI software,
+but
+.Xr nginx 8
+only supports FastCGI.
+I used
+.Xr slowcgi 8
+as a compatibility layer
+by adding the following to
+.Pa /etc/rc.conf :
+.Bd -literal -offset indent
+slowcgi_enable="YES"
+slowcgi_flags="-p / -s /var/run/slowcgi.sock"
+.Ed
+.
+.Ss nginx
+I added the following in a new
+.Cm server
+block to
+.Pa /usr/local/etc/nginx/nginx.conf :
+.Bd -literal -offset indent
+root /usr/local/www/cgit;
+location / {
+	try_files $uri @cgit;
+}
+location @cgit {
+	fastcgi_pass unix:/var/run/slowcgi.sock;
+	fastcgi_param SCRIPT_FILENAME $document_root/cgit.cgi;
+	fastcgi_param SCRIPT_NAME /;
+	fastcgi_param PATH_INFO $uri;
+	fastcgi_param QUERY_STRING $query_string;
+	fastcgi_param REQUEST_METHOD $request_method;
+	fastcgi_param CONTENT_TYPE $content_type;
+	fastcgi_param CONTENT_LENGTH $content_length;
+	fastcgi_param HTTPS $https if_not_empty;
+	fastcgi_param SERVER_PORT $server_port;
+	fastcgi_param SERVER_NAME $server_name;
+}
+.Ed
+.
+.Pp
+The
+.Cm try_files
+directive causes
+.Xr nginx 8
+to first try to serve static files from
+.Pa /usr/local/www/cgit
+before passing anything else on to FastCGI.
+.
+.Pp
+The
+.Va SCRIPT_FILENAME
+parameter tells
+.Xr slowcgi 8
+the path of the CGI binary to run.
+Setting
+.Va SCRIPT_NAME
+to
+.Pa /
+tells cgit its root URL
+and avoids it using query strings for everything.
+.
+.Ss cgit
+cgit doesn't provide any configuration to start from,
+so you have to just read
+.Xr cgitrc 5 .
+I added the following to
+.Pa /usr/local/etc/cgitrc :
+.Bd -literal -offset indent
+cache-size=1024
+clone-url=https://$HTTP_HOST/$CGIT_REPO_URL
+snapshots=tar.gz zip
+remove-suffix=1
+enable-git-config=1
+scan-path=/home/june/pub
+.Ed
+.
+.Pp
+The
+.Cm cache-size
+option enables caching,
+which by default is stored in
+.Pa /var/cache/cgit ,
+so I made sure that directory exists
+and is writable by the
+.Sy www
+user.
+The
+.Cm clone-url
+option sets the clone URL to advertise.
+cgit will automatically serve git over HTTP.
+The
+.Cm snapshots
+option makes tarballs available for tags and commits.
+.
+.Pp
+The
+.Cm scan-path
+option causes cgit to scan the given path
+for git repositories.
+I'm putting mine in
+.Pa ~/pub .
+The
+.Cm remove-suffix
+option causes cgit to remove the
+.Pa .git
+suffix from the URLs it uses
+for the repositories it finds,
+so that
+.Pa ~/pub/pounce.git
+is served at
+.Pa /pounce .
+The
+.Cm enable-git-config
+option allows controlling some cgit options
+from the
+.Xr git-config 1
+of each repository.
+See
+.Sx git
+below.
+.
+.Pp
+I also set up a filter to render
+.Xr mdoc 7
+files
+and do syntax highlighting
+by adding the following to
+.Pa cgitrc :
+.Bd -literal -offset indent
+readme=:README.7
+readme=:README
+about-filter=/usr/local/libexec/cgit-filter
+source-filter=/usr/local/libexec/cgit-filter
+.Ed
+.
+.Pp
+The
+.Cm readme
+options tell cgit which files to look for
+to render the
+.Dq about
+page.
+The colon prefix causes it to look for them
+in the git tree.
+The
+.Pa /usr/local/libexec/cgit-filter
+script contains the following:
+.Bd -literal -offset indent
+#!/bin/sh
+case "$1" in
+	(*.[1-9])
+		/usr/bin/mandoc -T utf8 | /usr/local/libexec/ttpre
+		;;
+	(*)
+		exec /usr/local/libexec/hi -t -n "$1" -f html -o anchor
+		;;
+esac
+.Ed
+.
+.Pp
+Filter scripts are run with the filename as their first argument
+and the contents of the file on standard input.
+The
+.Xr ttpre 1
+command is my own utility to convert
+.Xr man 1
+output to HTML.
+The
+.Xr hi 1
+command is my own
+.Lk https://causal.agency/bin/hi.html "syntax highlighter" .
+.
+.Ss git
+I create my repositories in
+.Pa ~/pub
+with
+.Ql git init --bare
+and use
+.Pa git.causal.agency:pub/example.git
+locally as the remote.
+Descriptions are set by editing the
+.Pa description
+file in each repository.
+The section and homepage can be set with
+.Xr git-config 1
+through the keys
+.Cm cgit.section
+and
+.Cm cgit.homepage ,
+respectively,
+thanks to the
+.Cm enable-git-config
+option above.
+.
+.Ss Redirects
+I added the following to the
+.Cm server
+block that used to serve gitea in
+.Pa nginx.conf :
+.Bd -literal -offset indent
+location ~* /june/([^.]+)[.]git(.*) {
+	return 301 https://git.causal.agency/$1$2?$query_string;
+}
+location ~* /june/([^/]+) {
+	return 301 https://git.causal.agency/$1;
+}
+location / {
+	return 301 https://git.causal.agency;
+}
+.Ed
+.
+.Pp
+This redirects any links to my gitea repos
+to the corresponding repo in cgit.
+The first
+.Sy location
+block also redirects gitea HTTP clone URLs to cgit
+so that
+.Xr git-pull 1
+continues to work on existing clones.
+.
+.Ss Update: fast HTTPS clones
+Someone pointed out that cloning my repos
+over HTTPS was incredibly slow,
+and this is because cgit only implements the
+.Dq dumb
+HTTP git transport.
+To speed up cloning,
+I send the URLs used by the
+.Dq smart
+HTTP transport to
+.Xr git-http-backend 1
+instead:
+.Bd -literal -offset indent
+location ~ /.+/(info/refs|git-upload-pack) {
+	fastcgi_pass unix:/var/run/slowcgi.sock;
+	fastcgi_param SCRIPT_NAME /usr/local/libexec/git-core/git-http-backend;
+	fastcgi_param GIT_HTTP_EXPORT_ALL 1;
+	fastcgi_param GIT_PROJECT_ROOT /home/june/pub;
+	include fastcgi_params;
+}
+.Ed
+.
+.Pp
+I factored out the FastCGI parameters
+I'm using with cgit
+to be included here as well.
+.
+.Sh AUTHORS
+.An June Bug Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/008-how-irc.7 b/www/text.causal.agency/008-how-irc.7
new file mode 100644
index 00000000..aba1bbf9
--- /dev/null
+++ b/www/text.causal.agency/008-how-irc.7
@@ -0,0 +1,193 @@
+.Dd March  8, 2020
+.Dt HOW-IRC 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm How I Relay Chat
+.Nd in code
+.
+.Sh DESCRIPTION
+I've been writing a lot of IRC software lately
+.Pq Sx SEE ALSO ,
+and developed some nice code patterns
+that I've been reusing.
+Here they are.
+.
+.Ss Parsing
+I use fixed size buffers almost everywhere,
+so it's necessary to know IRC's size limits.
+A traditional IRC message is a maximum of 512 bytes,
+but the IRCv3 message-tags spec adds
+(unreasonably, in my opinion)
+8191 bytes for tags.
+IRC messages also have a maximum of 15 command parameters.
+.Bd -literal -offset indent
+enum { MessageCap = 8191 + 512 };
+enum { ParamCap = 15 };
+.Ed
+.
+.Pp
+If I'm using tags,
+I'll use X macros
+to declare the set I care about.
+X macros are a way of maintaining parallel arrays,
+or in this case an enum and an array.
+.Bd -literal -offset indent
+#define ENUM_TAG \e
+	X("msgid", TagMsgid) \e
+	X("time", TagTime)
+
+enum Tag {
+#define X(name, id) id,
+	ENUM_TAG
+#undef X
+	TagCap,
+};
+
+static const char *TagNames[TagCap] = {
+#define X(name, id) [id] = name,
+	ENUM_TAG
+#undef X
+};
+.Ed
+.
+.Pp
+The TagNames array is used by the parsing function
+to assign tag values into the message structure,
+which looks like this:
+.Bd -literal -offset indent
+struct Message {
+	char *tags[TagCap];
+	char *nick;
+	char *user;
+	char *host;
+	char *cmd;
+	char *params[ParamCap];
+};
+.Ed
+.
+.Pp
+I'm a fan of using
+.Xr strsep 3
+for simple parsing.
+Although it modifies its input
+(replacing delimiters with NUL terminators),
+since the raw message is in a static buffer,
+it is ideal for so-called zero-copy parsing.
+I'm not going to include the whole parsing function here,
+but I will at least include the part that many get wrong,
+which is dealing with the colon-prefixed trailing parameter:
+.Bd -literal -offset indent
+msg.cmd = strsep(&line, " ");
+for (int i = 0; line && i < ParamCap; ++i) {
+	if (line[0] == ':') {
+		msg.params[i] = &line[1];
+		break;
+	}
+	msg.params[i] = strsep(&line, " ");
+}
+.Ed
+.
+.Ss Handling
+To handle IRC commands and replies
+I add handler functions to a big array.
+I usually have some form of helper as well
+to check the number of expected parameters.
+.Bd -literal -offset indent
+typedef void HandlerFn(struct Message *msg);
+
+static const struct Handler {
+	const char *cmd;
+	HandlerFn *fn;
+} Handlers[] = {
+	{ "001", handleReplyWelcome },
+	{ "PING", handlePing },
+	{ "PRIVMSG", handlePrivmsg },
+};
+.Ed
+.
+.Pp
+Since I keep these arrays sorted anyway,
+I started using the standard
+.Xr bsearch 3
+function,
+but a basic for loop probably works just as well.
+I do wish I could compile-time assert
+that the array really is sorted, though.
+.Bd -literal -offset indent
+static int compar(const void *cmd, const void *_handler) {
+	const struct Handler *handler = _handler;
+	return strcmp(cmd, handler->cmd);
+}
+
+void handle(struct Message msg) {
+	if (!msg.cmd) return;
+	const struct Handler *handler = bsearch(
+		msg.cmd,
+		Handlers, ARRAY_LEN(Handlers),
+		sizeof(*handler), compar
+	);
+	if (handler) handler->fn(&msg);
+}
+.Ed
+.
+.Ss Capabilities
+For IRCv3 capabilties
+I use X macros again,
+this time with another handy macro
+for declaring bit flag enums.
+.Bd -literal -offset indent
+#define BIT(x) x##Bit, x = 1 << x##Bit, x##Bit_ = x##Bit
+
+#define ENUM_CAP \e
+	X("message-tags", CapMessageTags) \e
+	X("sasl", CapSASL) \e
+	X("server-time", CapServerTime)
+
+enum Cap {
+#define X(name, id) BIT(id),
+	ENUM_CAP
+#undef X
+};
+
+static const char *CapNames[] = {
+#define X(name, id) [id##Bit] = name,
+	ENUM_CAP
+#undef X
+};
+.Ed
+.
+.Pp
+The
+.Fn BIT
+macro declares, for example,
+.Dv CapSASL
+as the bit flag and
+.Dv CapSASLBit
+as the corresponding index.
+The
+.Vt "enum Cap"
+is used as a set,
+for example checking if SASL is enabled with
+.Ql caps & CapSASL .
+.
+.Pp
+These patterns are serving my IRC software well,
+and my IRC projects are serving me well.
+It is immensely satisfying
+to be (near) constantly using software
+that I wrote myself and am happy with,
+regardless of how niche it may be.
+.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Lk https://git.causal.agency/pounce/about "IRC bouncer"
+.It
+.Lk https://git.causal.agency/litterbox/about "IRC logger"
+.It
+.Lk https://git.causal.agency/catgirl/about "IRC client"
+.El
+.
+.Sh AUTHORS
+.An June Bug Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/009-casual-update.7 b/www/text.causal.agency/009-casual-update.7
new file mode 100644
index 00000000..0548436a
--- /dev/null
+++ b/www/text.causal.agency/009-casual-update.7
@@ -0,0 +1,127 @@
+.Dd May  6, 2020
+.Dt CASUAL-UPDATE 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm casual update
+.Nd software developments
+.
+.Sh DESCRIPTION
+I've been figuring out more of IMAP
+and Internet Messages in general
+while working on a new project
+so I've revisited some older ones.
+I've copied my somewhat more proper
+IMAP parsing code into them,
+so they should be more robust.
+.
+.Pp
+.Xr imbox 1
+is my tool to export messages
+in mboxrd format directly from IMAP.
+It's mostly for applying patches sent by email
+without having any kind of local mail setup.
+For that,
+it includes the
+.Xr git-fetch-email 1
+wrapper which works very similarly to
+.Xr git-send-email 1 .
+I learned by reading the source of
+.Xr git-subtree 1
+that
+.Xr git-rev-parse 1
+can be used by shell scripts
+to parse long options,
+so I added those.
+I also added the
+.Fl Fl apply
+flag to automatically pipe to
+.Xr git-am 1
+with the right flags for mboxrd.
+.
+.Pp
+.Xr notemap 1
+is a tool for mirroring text files
+to an IMAP Notes mailbox,
+which is used by FastMail's web UI
+and the macOS/iOS Notes app.
+Its original parsing code
+was particularly ad-hoc.
+Since I've now learned
+how UTF-8 headers are encoded,
+I updated it to properly encode
+the file name in the Subject line.
+.
+.Pp
+I also got distracted by
+a conversation about UNIX-domain sockets
+where I was comparing the macOS and FreeBSD
+.Xr unix 4
+pages and the Linux
+.Xr unix 7
+page.
+This lead me to make
+.Xr exman 1 ,
+a tool to locally install and read
+manual pages for Linux, POSIX,
+.Fx ,
+.Nx
+and
+.Ox .
+I've already gotten quite a bit of use out of it.
+.
+.Pp
+In yet another IRC distraction,
+I was talking about some further plans for my IRC software,
+and realized it might be time to write
+my future projects list down.
+I opened a
+.Pa .plan
+file,
+immediately wondered how anyone can write plain text,
+then switched to a
+.Pa plan.7
+file.
+There's nothing I won't use
+.Xr mdoc 7
+for.
+After a little setup,
+I can now be fingered,
+and make jokes about this silly little protocol
+from the days of old.
+.Xr finger 1 Ap s
+default output fills me with joy:
+.Bd -unfilled -offset indent
+No Mail.
+No Plan.
+.Ed
+.
+.Pp
+And speaking of IRC and plans,
+I've been meaning to tag
+.Xr catgirl 1
+version 1.0 for a while now.
+I've been using it as my main client
+and my commits to it have really slowed down.
+When I do tag it,
+I'm planning on writing another post
+about my whole
+.Dq suite
+of IRC software
+and how the parts work together.
+Watch this space.
+.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Lk https://git.causal.agency/imbox "imbox"
+.It
+.Lk https://git.causal.agency/notemap "notemap"
+.It
+.Lk https://git.causal.agency/exman "exman"
+.It
+.Lk https://git.causal.agency/catgirl "catgirl"
+.El
+.
+.Sh AUTHORS
+.An June Bug Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/010-irc-suite.7 b/www/text.causal.agency/010-irc-suite.7
new file mode 100644
index 00000000..515a30ab
--- /dev/null
+++ b/www/text.causal.agency/010-irc-suite.7
@@ -0,0 +1,409 @@
+.Dd June 19, 2020
+.Dt IRC-SUITE 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm IRC suite
+.Nd my own IRC software
+.
+.Sh DESCRIPTION
+Over the past months
+.Po
+eight of them, according to
+.Xr git-log 1
+.Pc
+I developed a new
+.Dq suite
+of IRC software
+that I now use full-time,
+consisting of a bouncer,
+a new logging and search solution,
+and a terminal client.
+These new programs share some characteristics:
+they are all TLS-only
+and use the libtls API from LibreSSL,
+they can all be entirely configured from the command line
+or with equivalent configuration files,
+they are all designed as
+a one process to one IRC connection mapping,
+and they all take advantage of IRCv3 features.
+.
+.Pp
+For context,
+I was previously running
+the znc IRC bouncer
+and using the Textual IRC client
+with its plain text logs.
+I also continue to use
+the Palaver IRC client for iOS.
+.
+.Ss Background
+A bouncer is a piece of server software
+that stays connected to IRC at all times
+and acts as a relay
+between your client and the IRC server.
+When the client is disconnected,
+the bouncer buffers incoming messages
+to send to the client when it reconnects.
+.
+.Pp
+Aside from this,
+bouncers have another advantage:
+client multiplexing.
+Several clients,
+for instance on different computers
+or a phone,
+should be able to connect to the same bouncer,
+and send and receive messages under the same nick.
+Unfortunately,
+znc does not handle this use-case well at all.
+Out of the box it offers two options:
+either any client connection totally clears the buffer,
+causing other clients to miss chat history;
+or the buffer is never cleared,
+causing every client connection
+to be repeatedly spammed with redundant history.
+There is also a znc wiki page
+that suggests one way to solve this issue
+is to connect znc to itself multiple times over.
+Yikes.
+.
+.Ss pounce
+My dissatisfaction with
+connecting multiple clients to znc
+directly motivated me to start working
+on a new multi-client-focused IRC bouncer.
+The result is
+.Xr pounce 1 ,
+based on a rather straightforward
+single-producer (the IRC server)
+multiple-consumer (each IRC client)
+ring buffer.
+Each client has its own
+independent position in the buffer
+so can properly be brought up to date
+whenever it connects.
+.
+.Pp
+Additionally,
+by assuming support for the IRCv3
+.Sy server-time
+extension,
+all IRC events can be accurately
+relayed to clients at any time,
+and the internals of
+.Xr pounce 1
+can be kept very simple.
+In fact,
+it completely avoids parsing most IRC messages,
+simply pushing them into the buffer
+with an associated timestamp.
+.
+.Pp
+The usernames sent by clients during registration
+are used as opaque identifiers for buffer consumers.
+This was chosen since most clients
+can be configured to send an arbitrary username,
+and those that don't often default
+to the name of the client itself,
+making it an appropriate identifier.
+.
+.Pp
+Later,
+I added a way for clients
+to be informed of their own buffer positions
+using a vendor-specific IRCv3 capability.
+This means a client
+can save the position
+of the last message it actually received,
+and request to set its position
+when it reconnects,
+ensuring no messages are lost
+to network issues
+or software crashes.
+.
+.Ss calico
+Due to the simple design of mapping
+one process to one IRC (server) connection,
+it is necessary to run several instances of
+.Xr pounce 1 .
+Initially I simply used different ports for each,
+but as I connected to more networks
+and even ran some instances for friends,
+it became less feasible.
+.
+.Pp
+The solution I came up with
+was to dispatch incoming connections
+using Server Name Indication, or SNI.
+This way,
+multiple domains pointing to the same host
+could be used with only one port
+to connect to different instances of
+.Xr pounce 1 .
+For example,
+I use a
+.Li *.irc.causal.agency
+wildcard DNS entry
+and a subdomain for each IRC network,
+all on port 6697.
+.
+.Pp
+The
+.Xr calico 1
+daemon included with pounce
+accomplishes this dispatch
+using the
+.Dv MSG_PEEK
+flag of
+.Xr recvmsg(2)
+on incoming connections.
+Since SNI is immediately sent by TLS clients
+as part of the ClientHello message in clear-text,
+it can be processed
+without doing any actual TLS.
+The connection itself is then
+sent to the corresponding
+.Xr pounce 1
+instance
+over UNIX-domain socket,
+which handles TLS as normal.
+This means that
+.Xr calico 1
+and
+.Xr pounce 1
+operate entirely independently of each other.
+.
+.Ss litterbox
+Based on the multiple-consumer ring buffer design,
+I realized it would be easy
+to implement additional functionality
+as independent purpose-built clients
+which connect to
+.Xr pounce 1
+alongside regular clients.
+This could allow dedicated OTR or DCC software
+to operate in parallel with a basic client,
+or for more passive software
+to provide notifications
+or dedicated logging.
+.
+.Pp
+For the latter,
+I wanted to do better than
+plain text log files.
+.Xr grep 1
+over files works fine,
+but search could be faster and smarter,
+and the text format is
+more lossy and less structured
+than I'd like it to be.
+Conveniently,
+SQLite provides an extension
+(actually two)
+for full-text search.
+.
+.Pp
+The litterbox project
+is my dedicated logging solution
+using SQLite FTS5.
+It consists of three tools:
+the
+.Xr litterbox 1
+daemon itself which connects to pounce
+and logs messages to SQLite,
+the
+.Xr scoop 1
+command line query tool,
+and the
+.Xr unscoop 1
+plain text import tool.
+The
+.Xr scoop 1
+tool constructs SQL queries
+and formats the results for viewing,
+with coloured nicks
+and piped to a pager
+by default.
+.
+.Pp
+The
+.Xr litterbox 1
+daemon
+can also provide a simple
+.Dq online
+.Pq over IRC
+search query interface
+to other connected clients.
+The simplest way to allow different
+.Xr pounce 1
+clients to talk to each other
+was to route private messages to self
+internally without sending them to the IRC server.
+So from any client
+I can simply message myself
+a full-text search query
+and
+.Xr litterbox 1
+responds with the results.
+.
+.Pp
+Along with routing self-messages,
+.Xr pounce 1
+also provides a vendor-specific IRCv3 capability
+for passive clients such as
+.Xr litterbox 1
+to indicate that they should not influence
+the automatic away status,
+which is normally only set
+when no clients are connected.
+.
+.Pp
+An advantage of this architecture
+of dedicated clients
+rather than bouncer modules
+is that they need not run
+on the same host.
+I run my bouncers on a VPS,
+but I'd rather not store my private logs there,
+so
+.Xr litterbox 1
+runs instead on a Raspberry Pi
+in my apartment.
+Also,
+since it is essentially
+just a regular IRC bot,
+it could be used independently
+for keeping public logs for a channel.
+.
+.Ss catgirl
+There's not really that much to say
+about the client,
+.Xr catgirl 1 .
+Of the three projects
+it contains the most code
+but is also the least interesting,
+in my opinion.
+It just does what I want a client to do,
+and gets the details right.
+.
+.Pp
+Tab complete is ordered by most recently seen or used,
+and completing several nicks
+inserts commas between them
+as well as the colon following the final nick.
+In the input line,
+the prompt is updated
+to reflect whether the input
+will be interpreted as a command or as a message.
+Messages are automatically scanned for URLs,
+which can be opened or copied with commands
+specifying the nick or a substring of the URL.
+.
+.Pp
+Scrolling in a window creates a split view,
+keeping the latest messages visible.
+Nick colours are based instead on usernames,
+keeping them more stable across renames,
+and mentions in messages are coloured
+to make the conversation easier to follow.
+The visibility of ignored messages
+can be toggled at any time.
+Channels can be muted
+so their activity is hidden
+from the status line
+unless you are pinged.
+.
+.Pp
+.Xr catgirl 1
+is configured entirely on the command line
+or in equivalent simple configuration files.
+There's no dynamic manipulation of state
+using complex
+.Ql /
+commands like in some other clients.
+.
+.Pp
+The major caveat is that
+.Xr catgirl 1
+connects to only one network at a time.
+This keeps the configuration, the interface
+and the code much simpler.
+.Xr tmux 1 ,
+.Xr screen 1
+or a tabbed terminal emulator
+are good options to run several instances.
+.
+.Pp
+If you're interested in giving
+.Xr catgirl 1
+a quick (and necessarily limited) try,
+you can
+.Li ssh chat@ascii.town .
+.
+.Ss Future
+I think I'm done with IRC software for now.
+As mentioned above,
+there are a few more pieces
+that could fit in to this setup,
+but I don't really want or need them right now.
+One thing I definitely want to try
+at some point
+is adding a litterbox component
+to index the contents of URLs
+to make finding previously shared links easier.
+.
+.Pp
+If you try any of this software
+and have feedback,
+let me know in
+.Li #ascii.town
+on tilde.chat
+or by email.
+And of course,
+patches are always welcome.
+.
+.Ss Update: scooper
+Somehow I had the motivation
+to create a web interface for litterbox:
+.Xr scooper 1 .
+It can be used either as CGI
+or as a FastCGI worker,
+and I used the excellent
+.Xr kcgi 3
+library for it.
+.
+.Pp
+The main advantage of this interface
+is that you can click on a search result
+to be brought to its context in the log viewer.
+I also added an option to
+.Xr litterbox 1
+to provide a corresponding scooper link
+in response to its query interface.
+.
+.Pp
+A small demo of scooper is hosted at
+.Aq Lk "https://causal.agency/scooper/" .
+It publicly logs the
+.Li #litterbox
+channel on tilde.chat.
+.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Lk "https://git.causal.agency/pounce" pounce
+.It
+.Lk "https://git.causal.agency/litterbox" litterbox
+.It
+.Lk "https://git.causal.agency/catgirl" catgirl
+.It
+.Lk "https://www.sqlite.org/fts5.html" "SQLite FTS5 Extension"
+.It
+.Lk "https://git.causal.agency/scooper" scooper
+.It
+.Lk "https://kristaps.bsd.lv/kcgi/" kcgi
+.El
+.
+.Sh AUTHORS
+.An June Bug Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/011-libretls.7 b/www/text.causal.agency/011-libretls.7
new file mode 100644
index 00000000..c29c325e
--- /dev/null
+++ b/www/text.causal.agency/011-libretls.7
@@ -0,0 +1,220 @@
+.Dd August  9, 2020
+.Dt LIBRETLS 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm LibreTLS
+.Nd libtls for OpenSSL
+.
+.Sh DESCRIPTION
+This is a sort of announcement post about LibreTLS,
+my port of libtls from LibreSSL to OpenSSL.
+If you've wanted to try any of my software
+but have been unable to because of LibreSSL,
+LibreTLS is an option that will likely work for you.
+I'm including instructions
+for building it and my IRC software
+on Debian as an example,
+since manually installing libraries
+is less straightforward than it could be.
+.
+.Pp
+libtls is
+.Do
+a new TLS library,
+designed to make it easier to write foolproof applications
+.Dc .
+It was developed as part of LibreSSL,
+.Ox Ap s
+fork of OpenSSL,
+and is implemented against their version of libssl.
+It provides a nice high-level API
+for TLS sockets,
+with functions like
+.Xr tls_connect 3 ,
+.Xr tls_read 3
+and
+.Xr tls_write 3 .
+This is a vast improvement over libssl's
+confusing mess of an API!
+Its relative obscurity is a real shame
+for C programmers.
+.
+.Pp
+An obvious cause of its obscurity
+is that it is tied to LibreSSL.
+Although LibreSSL is available
+for platforms other than
+.Ox ,
+it conflicts with OpenSSL
+so is difficult to install alongside it
+and is often not packaged at all.
+Additionally,
+even if a user manually installs LibreSSL,
+libtls is likely not to work on some distros
+due to its hardcoded CA bundle file path.
+.
+.Pp
+Since libtls is implemented against libssl,
+which originates in OpenSSL,
+it should be possible to use libtls with it.
+This is what I set out to do in LibreTLS.
+I started by importing the sources
+from a LibreSSL-portable release,
+then worked on porting the portions
+that were incompatible with OpenSSL.
+.
+.Pp
+The simpler changes just involved
+replacing internal struct field accesses
+with public APIs.
+libtls accesses libssl internals
+using a hack to get the header files
+to declare private struct fields,
+and for basically no reason.
+The bigger changes involved
+reimplementing some functions
+which only exist in LibreSSL,
+but these were still quite small.
+I also imported the necessary compatibility functions
+from LibreSSL's libcrypto
+and adapated the autotools build files
+to produce only a libtls
+which depends on OpenSSL.
+.
+.Pp
+Along the way
+I decided to make one small behavioural change
+in order for LibreTLS to be more likely
+to work for everyone.
+I removed the hardcoded CA file path
+and changed the default configuration
+to use OpenSSL's default CA paths,
+which include a CA directory.
+This seems to be the preferred CA source
+on systems such as Debian,
+where the default CA file path doesn't exist.
+.
+.Pp
+I think the reason LibreSSL
+wants to avoid using a CA directory
+is so that it can fully load the CA file
+once before being sandboxed.
+However,
+using OpenSSL's default configuration,
+the CA file will still be loaded immediately
+if it exists.
+If it doesn't exist,
+sandboxed applications
+will fail when trying to
+load certificates from the directory,
+but unsandboxed applications
+will work just fine.
+Since LibreSSL's libtls
+would fail either way,
+I think the new behaviour
+is an improvement.
+.
+.Pp
+Another advantage of separating libtls from LibreSSL
+is that it is unencumbered by OpenSSL's
+awkward double-license,
+both of which are incompatible with the GPL.
+libtls is all new ISC-licensed code,
+and future versions of OpenSSL (3.0)
+will be released under the Apache 2.0 license,
+which is compatible with GPLv3.
+In the future,
+GPL software will be able to link with
+libtls and OpenSSL without additional permissions.
+.
+.Pp
+It's also worth noting that LibreSSL
+likely will not be able to import any code
+from future versions of OpenSSL,
+since Apache 2.0 is on
+.Ox Ap s
+license shitlist.
+LLVM is also slowly changing their license
+to Apache 2.0,
+so it'll be interesting to see what
+.Ox
+does.
+.
+.Ss Installing Manually
+To install LibreTLS on Debian,
+for example,
+fetch a release tarball from
+.Lk https://causal.agency/libretls/
+and install the build dependencies:
+.Bd -literal -offset indent
+sudo apt-get install build-essential libssl-dev pkgconf
+.Ed
+.
+.Pp
+.Xr pkgconf 1
+isn't a dependency of LibreTLS itself,
+but it's how my software
+configures its build
+for a dependency on libtls.
+The usual build steps
+will install the library:
+.Bd -literal -offset indent
+\&./configure
+make all
+sudo make install
+.Ed
+.
+.Pp
+The library will be installed in
+.Pa /usr/local/lib
+by default,
+and you need to make sure
+the dynamic linker
+will be able to find it there.
+On Debian,
+.Pa /usr/local/lib
+already appears in
+.Pa /etc/ld.so.conf.d/libc.conf ,
+but on other systems
+you'll probably need to add it to either
+.Pa /etc/ld.so.conf
+or a new file such as
+.Pa /etc/ld.so.conf.d/local.conf .
+Once the library is installed
+and the path is configured,
+the linker cache needs to be refreshed:
+.Bd -literal -offset indent
+sudo ldconfig
+.Ed
+.
+.Pp
+You'll probably also need to set
+.Ev PKG_CONFIG_PATH
+for the configure scripts
+of my software:
+.Bd -literal -offset indent
+PKG_CONFIG_PATH=/usr/local/lib/pkgconfig ./configure
+.Ed
+.
+.Pp
+On
+.Fx ,
+LibreTLS and some of my IRC software
+can be installed from my own
+.Lk https://git.causal.agency/ports/ "ports tree"
+.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Lk https://git.causal.agency/libretls/about LibreTLS
+.It
+.Lk https://man.openbsd.org/tls_init.3 "libtls API documentation"
+.El
+.
+.Pp
+Another alternative libtls implementation,
+.Lk https://sr.ht/~mcf/libtls-bearssl/ "libtls-bearssl"
+.
+.Sh AUTHORS
+.An June Bug Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/012-inability.7 b/www/text.causal.agency/012-inability.7
new file mode 100644
index 00000000..d352143b
--- /dev/null
+++ b/www/text.causal.agency/012-inability.7
@@ -0,0 +1,39 @@
+.Dd November 26, 2020
+.Dt INABILITY 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Inability
+.Nd losing the ability to create
+.
+.Sh DESCRIPTION
+For often weeks, sometimes months at a time,
+I lose the ability to write new code.
+I can still make fixes
+and little cleanups
+in my existing projects,
+but if I try to work on something new,
+nothing happens.
+I can't get anything done.
+.
+.Pp
+I think it's now been
+over 3 months
+since I've created anything.
+I don't know what to do about it.
+In the past I've eventually
+regained the ability to code,
+but it's unclear to me how or why.
+I also don't know what
+I should be doing instead.
+Writing code is the only hobby
+I've ever really developed,
+so without it I basically
+don't do anything.
+.
+.Pp
+Does this happen to anyone else?
+How do you cope?
+.
+.Sh AUTHORS
+.Mt june@causal.agency
diff --git a/www/text.causal.agency/013-hot-tips.7 b/www/text.causal.agency/013-hot-tips.7
new file mode 100644
index 00000000..63b6e353
--- /dev/null
+++ b/www/text.causal.agency/013-hot-tips.7
@@ -0,0 +1,156 @@
+.Dd December  2, 2020
+.Dt HOT-TIPS 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm hot tips
+.Nd from my files
+.
+.Sh DESCRIPTION
+This is a short list of tips
+from my configuration files and code
+that might be useful.
+.
+.Ss Shell
+.Bl -tag -width Ds
+.It CDPATH=:~
+This is useful if you sometimes type,
+for example,
+.Ql cd src/bin
+wanting to go to
+.Pa ~/src/bin
+but you aren't in
+.Pa ~ .
+If the path doesn't exist
+in the current directory,
+.Ic cd
+will try it in
+.Pa ~
+as well.
+.
+.It alias ls='LC_COLLATE=C ls'
+This makes it so that
+.Xr ls 1
+lists files in ASCIIbetical order,
+which puts capitalized names like
+.Pa README
+and
+.Pa Makefile
+first.
+.
+.It git config --global commit.verbose true
+Not shell but close enough.
+This makes it so the entire diff is shown
+below the usual summary
+in the editor for a
+.Xr git-commit(1)
+message.
+Useful for doing a quick review
+of what you're committing.
+.El
+.
+.Ss (neo)vim
+.Bl -tag -width Ds
+.It set inccommand=nosplit
+This is the only
+.Xr nvim 1
+feature I really care about
+aside from the improved defaults.
+This provides a live preview of what a
+.Ic :s
+substitution command will do.
+It makes it much easier to
+write complex substitutions.
+.
+.It nmap <leader>s vip:sort<CR>
+This mapping sorts the lines of a paragraph,
+or block of text separated by blank lines.
+I use this a lot to sort
+#include directives.
+.
+.It nmap <leader>S $vi{:sort<CR>
+Similar to the last mapping,
+this one sorts lines inside braces.
+I use this to sort
+switch statement cases
+or array initializers.
+.
+.It nmap <leader>a m':0/^#include <<CR>:nohlsearch<CR>O#include <
+I use this mapping to add new
+#include directives,
+usually followed by
+.Ic <leader>s
+and
+.Ic ''
+to sort them
+and return to where I was.
+.
+.It nmap <leader>d :0delete<CR>:0read !date +'.Dd \e%B \e%e, \e%Y'<CR>
+I use this to replace the first line of
+.Xr mdoc 7
+files with the current date.
+.El
+.
+.Ss C
+.Bl -tag -width Ds
+.It #define Q(...) #__VA_ARGS__
+This is what I've started using
+to quote things like SQL statements
+or HTML fragments in C.
+Anything that happens to be valid C tokens,
+which is most code,
+can be quoted this way.
+Macros are not expanded
+inside the quoted part.
+You can embed (matched) quotes
+without having to escape them.
+Whitespace gets collapsed,
+so you can write nicely formatted multi-line SQL
+that doesn't mess up your debug logging,
+for example.
+.Bd -literal -offset indent
+const char *sql = Q(
+	INSERT OR IGNORE INTO names (nick, user, host)
+	VALUES (:nick, :user, :host);
+);
+.Ed
+.
+.It #define BIT(x) x##Bit, x = 1 << x##Bit, x##Bit_ = x##Bit
+I use this macro to declare bitflag enums.
+It takes advantage of
+auto-incrementing enum items
+so you don't need to set the values manually.
+You also get constants
+for both the bit index
+and the flag value
+for each item.
+.Bd -literal -offset indent
+enum Attr {
+	BIT(Bold),
+	BIT(Reverse),
+	BIT(Italic),
+	BIT(Underline),
+};
+.Ed
+.Pp
+For example,
+defines
+.Sy ItalicBit = 2
+and
+.Sy Italic = 1 << 2 .
+Ignore the extraneous constants.
+.
+.It typedef int FnType(const char *str, size_t len);
+You can just typedef function types!
+It annoys me more than it probably should
+that everyone writes ugly
+function pointer typedefs.
+Just stick
+.Sy typedef
+on the front of a function declaration
+and use
+.Vt FnType * .
+.El
+.
+.Sh AUTHORS
+.Mt june@causal.agency
diff --git a/www/text.causal.agency/014-using-vi.7 b/www/text.causal.agency/014-using-vi.7
new file mode 100644
index 00000000..e6a6a7a0
--- /dev/null
+++ b/www/text.causal.agency/014-using-vi.7
@@ -0,0 +1,135 @@
+.Dd January 11, 2021
+.Dt USING-VI 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Using vi
+.Nd simpler tools
+.
+.Sh DESCRIPTION
+Happy new year
+and hello from
+.Xr vi 1 !
+I'm in the mood to post something
+but not in the mood for
+.Dq social
+media.
+This one will probably be short.
+.
+.Pp
+Yesterday I was trying to work on sandboxing
+.Xr catgirl 1
+(that's the IRC client I work on)
+with
+.Xr pledge 2
+and
+.Xr unveil 2
+on
+.Ox ,
+as suggested by the maintainer of its port.
+I've done similar things before,
+but only on server software
+rather than user software.
+.
+.Pp
+Anyway I was in
+.Xr ssh 1
+to my
+.Ox
+VM
+.Po
+sadly I don't currently have any hardware to run
+.Ox
+on
+.Pc
+using my usual editor,
+which is
+.Xr nvim 1 .
+I'm honestly not very thrilled
+with what neovim is doing lately,
+but the cleaned up defaults
+make my configuration files happier.
+.
+.Pp
+The real problem with
+.Xr nvim 1 ,
+though,
+is that it's laggy as hell on
+.Ox .
+There is significant delay
+on every single keystroke,
+as if I'm typing remotely to a server
+on the other side of the world,
+but this is on a local VM!
+.
+.Pp
+So I did the only reasonable thing:
+I typed
+.Sy :qa
+followed by
+.Sy vi .
+The difference was astonishing.
+Typing and editing suddenly felt
+.Em physical
+again.
+(I put that in italics even though I know it won't render.)
+Not only was it a vast improvement over
+.Xr nvim 1
+in
+.Xr ssh 1
+in a VM,
+it was a marked improvement over
+.Xr nvim 1
+running locally and natively.
+.
+.Pp
+Now obviously
+.Xr vi 1
+doesn't have all the bells and whistles
+of newer editors,
+but of course the core editing model
+that makes
+.Xr vim 1
+and
+.Xr nvim 1
+so good is there,
+and in purer form,
+I think.
+The
+.Xr vi 1
+manual page
+is feasible to just sit down and read,
+and learn everything there is to know about the editor.
+I set up a basic configuration
+and got coding.
+.Bd -literal -offset indent
+export EXINIT='set ai ic sm sw=4 ts=4'
+.Ed
+.
+.Pp
+After I finished my
+.Xr pledge 2
+and
+.Xr unveil 2
+patch,
+I was so pleased with
+.Xr vi 1
+that I kept on using it
+yesterday and today
+for other work,
+and obviously to write this post.
+Despite the lack of editor amenities,
+its responsiveness and simplicity
+are enough to make using it
+.Em comfortable
+and perhaps
+.Em cosy .
+I'm not sure I'll ever use
+.Xr vi 1
+full-time,
+but for now I am much less likely
+to launch
+.Xr nvim 1 .
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/015-reusing-tags.7 b/www/text.causal.agency/015-reusing-tags.7
new file mode 100644
index 00000000..19546496
--- /dev/null
+++ b/www/text.causal.agency/015-reusing-tags.7
@@ -0,0 +1,155 @@
+.Dd January 17, 2021
+.Dt REUSING-TAGS 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm reusing tags
+.Nd beyond ctags
+.
+.Sh DESCRIPTION
+I've tried to start writing this post a couple times now
+and I keep getting bogged down in explanations,
+so I'm just going to tell you
+about some cool things I did
+and hope they make sense.
+.
+.Pp
+When I wrote my first syntax highlighter,
+I decided that function definitions
+should have anchor links,
+because line number anchor links
+are entirely useless
+if you expect the file to change at all.
+Since the syntax highlighter
+was somewhat deliberately just a big pile of regex,
+I hacked in more regex to try
+to identify function and type definitions.
+It wasn't elegant and it didn't always work well.
+It did work though,
+and I found the links very useful.
+.
+.Pp
+Recently I was thinking about
+the lexer generator
+.Xr lex 1
+and decided to
+rewrite the syntax highlighter
+using it.
+Really syntax highlighting
+is no different than lexical analysis.
+I ran into a problem though,
+trying to preserve my anchor link function,
+because really that should involve
+some amount of parsing.
+Trying to port my regex hacks to
+.Xr lex 1
+made the lexers way more complicated
+and less reliable,
+so I gave up on it for a while.
+.
+.Pp
+And then,
+probably in the shower,
+I realized I was approaching it
+completely from the wrong direction.
+There's already a tool that does what I want,
+and I already use it:
+.Xr ctags 1 .
+All I need to do is use its output
+to insert anchor links
+into my syntax highlighter output.
+In an afternoon I wrote
+.Xr htagml 1 ,
+which loads tag definitions for its input file,
+then scans through the input for where they match.
+It can either HTML-escape
+the input as it goes,
+or use already formatted HTML
+being piped into it from a syntax highlighter.
+.
+.Pp
+The result is three simple tools
+working together to accomplish
+what a more complex tool
+couldn't reliably achieve.
+I'm very pleased with it,
+and I've updated my site and cgit
+to use the new
+.Xr lex 1 Ns -based
+highlighter,
+.Xr ctags 1
+and
+.Xr htagml 1 .
+I'm currently missing a lexer for
+.Xr sh 1 ,
+but I plan to write it eventually.
+I also want to write a tool
+to generate tags for
+.Xr make 1 ,
+.Xr mdoc 7
+and perhaps
+.Xr sh 1 .
+The cool thing about generating more kinds of tags
+is that they'll not only improve
+the HTML output,
+they'll also be usable in my editor.
+.
+.Pp
+Speaking of generating different kinds of tags,
+I also wrote some scripts not too long ago
+for reading IETF RFCs offline.
+The plain text files are available to
+.Xr rsync 1 ,
+but they're hard to navigate on their own.
+By scanning the files for headings
+and generating tags,
+it allows jumping to sections using
+.Ic :ta
+or
+.Ic ^]
+in
+.Xr vi 1 .
+For
+.Xr nvim 1
+I also added an
+.Ic :RFC
+command to open an RFC by number
+and set up
+.Ic ^]
+to work optimally for them.
+.
+.Pp
+I'm still using
+.Xr vi 1
+for most of my editing,
+by the way.
+And of course
+.Xr ctags 1
+was made to work with it!
+Simple old tools
+are really doing it for me lately.
+.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Lk https://causal.agency/bin/htagml.html htagml
+.It
+.Lk https://causal.agency/bin/hilex.html hilex
+.It
+.Lk https://git.causal.agency/src/tree/doc/rfc rfctags
+.El
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
+.
+.Sh ADDENDUM
+.Xr catgirl 1 ,
+.Xr pounce 1 ,
+.Xr litterbox 1
+and
+.Xr scooper 1
+all have new releases,
+if you're using any of them.
+Also, this space is now
+available over gopher,
+if that's your sort of thing.
diff --git a/www/text.causal.agency/016-using-openbsd.7 b/www/text.causal.agency/016-using-openbsd.7
new file mode 100644
index 00000000..b843e3c3
--- /dev/null
+++ b/www/text.causal.agency/016-using-openbsd.7
@@ -0,0 +1,505 @@
+.Dd February 14, 2021
+.Dt USING-OPENBSD 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Using OpenBSD
+.Nd for real
+.
+.Sh DESCRIPTION
+Hello from
+.Ox !
+After wishing one too many times
+that I had a real BSD
+on a physical machine,
+I finally got around to
+just installing one on my
+mid-2014 MacBook Pro.
+I hadn't done it sooner
+because I didn't realize
+how easy it would be.
+It helped that I already had a
+.Dq Boot Camp
+partition with a disused Windows 8 install
+that I could replace.
+.
+.Pp
+I roughly followed an old jcs gist
+along with the
+.Ox
+Disk Setup guide.
+I'm once again happy
+that I bought a printer\(em
+they're very useful for instructions
+to install an operating system
+on your only usable computer.
+I set up encrypted softraid
+and the operating system
+installed smoothly.
+.
+.Pp
+Next I had to install rEFInd,
+since the default Mac boot manager
+is really not keen on booting much.
+Installing it requires using the
+macOS recovery partition these days.
+But there was a problem
+with my new boot menu:
+I was promised a picture of Puffy,
+and instead I just got some abstract coloured circles!
+Turns out a bunch of OS icons
+got removed from rEFInd at some point,
+and I had to rescue Puffy
+from the git history.
+.
+.Pp
+So I could happily boot
+.Ox
+by selecting Puffy,
+but I had no networking.
+I thought the wifi chip might be supported by
+.Xr bwfm 4 ,
+but I got unlucky and it's a BCM4360,
+which everything hates.
+Based on the jcs gist,
+I checked the list of hardware
+supported by the
+.Xr urtwn 4
+driver for a wifi dongle to order.
+Just having a clear list
+in the driver manual is wonderful.
+I went with the Edimax EW-7811Un v2,
+which I could get for around $20.
+It's nice and tiny,
+though it has a piercing blue LED
+(destroy all blue LEDs)
+which I had to cover with electrical tape.
+.
+.Pp
+I had to do one other thing
+before I could get it all working, though.
+When I had checked the
+.Xr urtwn 4
+hardware list,
+I had been looking at
+.Ox Ns -current ,
+but I had installed
+.Ox 6.8 ,
+and support for the v2 hardware
+I had bought was added after that release.
+So I downloaded a snapshot
+.Pa bsd.rd
+along with the
+.Xr urtwn 4
+firmware file
+to a USB drive
+and upgraded the system.
+.
+.Pp
+Connecting to wifi with
+.Xr ifconfig 8
+is a breeze, by the way,
+and then you just write the same thing to a
+.Xr hostname.if 5
+file to make it automatic.
+I wanted to use
+.Ox
+for exactly this reason:
+simple, consistent, cohesive, well-documented tools.
+.
+.Pp
+Finally, I got to configuring.
+The console is configured with
+.Xr wsconsctl 8 ,
+and similarly you can put the commands in
+.Xr wsconsctl.conf 5
+to have them run at boot.
+I added
+.Li display.brightness=50%
+to tone down the brightness,
+which is initially 100%,
+and
+.Li keyboard.backlight=0%
+to turn off those annoying lights.
+.Xr wsconsctl.conf 5
+is also where you can set
+trackpad settings if you're not using
+.Xr synaptics 4 .
+I ended up using:
+.Bd -literal -offset indent
+mouse1.tp.tapping=1
+mouse1.tp.scaling=0.2
+mouse1.reverse_scrolling=1
+.Ed
+.Pp
+This enables tapping with several fingers
+to simulate different mouse buttons,
+makes the cursor move at a reasonable speed
+and scrolling move in the right direction.
+I also set up my usual modified QWERTY layout.
+.
+.Pp
+For
+.Xr X 7
+I had enabled
+.Xr xenodm 1 ,
+which seems quite nice.
+It automatically prompts you to add your
+.Xr ssh 1
+keys to
+.Xr ssh-agent 1
+when you log in.
+One of the reasons I had not wanted
+to set up another graphical system
+is that I thought
+I would have to make too many choices,
+and that I would have to choose least bad options
+rather than actually good options,
+but
+.Ox
+already includes reasonable choices.
+I wanted to use
+.Xr cwm 1 ,
+so I started a basic
+.Pa .xsession
+file:
+.Bd -literal -offset indent
+\&. ~/.profile
+export LC_CTYPE=en_US.UTF-8
+xset r rate 175 m 5/4 0
+xmodmap ~/.config/X/modmap
+xrdb -load ~/.config/X/resources
+exec cwm -c ~/.config/cwm/cwmrc
+.Ed
+.
+.Pp
+The
+.Xr xset 1
+command sets keyboard repeat rate
+and mouse acceleration.
+I spent some time going through
+.Xr cwm 1 Ap s
+functions and writing up bindings
+that would get me something close enough
+to what I'm used to in macOS.
+Most importantly,
+putting everything on the 4 modifier (command key).
+.
+.Pp
+I also added key bindings on F1 and F2
+to adjust the brightness with
+.Xr xbacklight 1 ,
+and on F10, F11 and F12
+to adjust volume with
+.Xr sndioctl 1 .
+I'm not sure why the F keys
+just send regular F1, F2, etc.\&
+regardless of the Fn key.
+I don't use F keys for anything else though,
+so I'm not too concerned.
+Once again,
+.Xr sndioctl 1
+is such an easy straightforward tool:
+.Bd -literal -offset indent
+bind-key F10 "sndioctl output.mute=!"
+bind-key F11 "sndioctl output.level=-0.05"
+bind-key F12 "sndioctl output.level=+0.05"
+.Ed
+.
+.Pp
+For aesthetic configuration,
+I added a new output to my
+.Xr scheme 1
+colour scheme tool for
+.Xr X 7 Ns -style
+RGB and
+.Xr xterm 1
+resources.
+Normally I use the
+.Em Go Mono
+font,
+but since
+.Ox
+already includes
+.Em Luxi Mono ,
+which
+.Em Go Mono
+is based on,
+I used that.
+The most important configuration
+to make anything readable on a high-DPI display is:
+.Bd -literal -offset indent
+Xft.dpi: 144
+Xft.antialias: true
+Xft.hinting: false
+.Ed
+.
+.Pp
+I'm annoyed that I haven't found
+where these resources are actually documented.
+I would hope they'd be in
+.Xr Xft 3
+or something,
+but they're not.
+Anyway,
+turning off hinting
+seems absolutely necessary
+to prevent text from looking like garbage.
+.
+.Pp
+It seems that to get a reasonably sized cursor
+I need to install
+.Sy xcursor-dmz .
+I'd prefer if there wasn't this one
+extra package that I needed
+for a reasonable setup.
+Tangentially,
+I've never understood why
+the black versions of dmz cursors
+are called
+.Dq aa
+when it seems like that
+would stand for antialiasing
+or something.
+.Bd -literal -offset indent
+Xcursor.size: 64
+Xcursor.theme: dmz-aa
+.Ed
+.
+.Pp
+For a desktop background,
+I found a cute bitmap (little picture)
+of snowflakes already in the system
+and used colours from my usual scheme:
+.Bd -literal -offset indent
+xsetroot -bitmap /usr/X11R6/include/X11/bitmaps/xsnow \e
+	-bg rgb:14/13/0E -fg rgb:7A/49/55
+.Ed
+.
+.Pp
+Since I'd rather not install anything
+I don't have to,
+I went with the default
+.Xr xterm 1 .
+It seems more than adequate, honestly.
+I read through its RESOURCES
+section to configure it how I like.
+The important settings are
+.Sy XTerm*utf8
+and
+.Sy XTerm*metaSendsEscape .
+Since I'm used to copying and pasting on macOS,
+I added equivalent
+.Dq translations :
+.Bd -literal -offset indent
+XTerm*VT100*translations: #override \en\e
+	Super <Key>C: copy-selection(CLIPBOARD) \en\e
+	Super <Key>V: insert-selection(CLIPBOARD)
+.Ed
+.
+.Pp
+The next thing I needed
+was a clock and battery indicator.
+I actually had my battery die on me
+while I was doing all this,
+which reminded me.
+.Xr xclock 1
+would be perfect,
+but then I'd need something else
+for battery.
+There are a couple basic battery indicators
+for X in ports,
+but they're terribly ugly.
+I wanted something as simple as
+.Xr xclock 1 ,
+but that I could add some other text to.
+Then I realized I could just use
+.Xr xterm 1
+for that.
+To my
+.Pa xsession
+I added:
+.Bd -literal -offset indent
+xterm -name clock -geometry 14x1-0+0 -sl 0 -e clock &
+.Ed
+.Pp
+This places a little terminal
+in the top-right corner of the screen
+with no scrollback lines,
+running a script called
+.Pa clock .
+To have
+.Xr cwm 1
+treat it like a
+.Dq panel
+and show it on every desktop,
+I added this to my
+.Pa cwmrc :
+.Bd -literal -offset indent
+ignore clock
+autogroup 0 clock,XTerm
+.Ed
+.Pp
+The
+.Pa clock
+script simply uses
+.Xr date 1
+and
+.Xr apm 8
+to print the time and battery charge
+every minute:
+.Bd -literal -offset indent
+tput civis
+sleep=$(( 60 - $(date +'%S' | sed 's/^0//') ))
+while :; do
+	if [ $(apm -a) -eq 1 ]; then
+		printf '%3s%%' "$(apm -l)"
+	else
+		test $(apm -b) -eq 2 && tput setaf 1 bold
+		printf '%3.3sm' "$(apm -m)"
+		tput sgr0
+	fi
+	printf ' %s\r' "$(date +'%a %H:%M')"
+	sleep $sleep
+	sleep=60
+done
+.Ed
+.Pp
+The initial setting of
+.Va sleep
+is to align the updates
+with the minute ticking over.
+I made the battery output
+a bit fancier by showing
+percentage while charging,
+minutes left while discharging,
+and highlighting in red
+when the battery is
+.Dq critical .
+.
+.Pp
+Now is a good time to mention adding
+.Ql apmd_flags=-A
+to
+.Pa /etc/rc.conf.local
+to enable
+.Dq automatic performance adjustment ,
+or not running your battery flat
+as fast as possible mode.
+It seems like I can get up to 3 hours
+of battery life depending on the screen brightness,
+but this is quite an old battery by now.
+.
+.Pp
+The other thing I needed
+was something to tone down
+that awful, evil blue light from the screen.
+I asked around and someone told me about
+.Xr sct 1 ,
+originally written by tedu.
+The package also includes a little
+.Xr sctd 1
+script that you can add to your
+.Pa .xsession
+to have it automatically adjust
+the colour temperature throughout the day.
+My eyes are no longer being assaulted.
+.
+.Pp
+While I was doing all this,
+I of course needed to talk about it on IRC,
+and it was very nice to be able to
+install my own IRC client with:
+.Bd -literal -offset indent
+doas pkg_add catgirl
+.Ed
+.Pp
+I don't plan to do
+general Web Browsing on
+.Ox ,
+and there is definitely
+no good choice for browser,
+so I just installed
+.Xr imv 1 ,
+.Xr mpv 1 ,
+.Xr youtube-dl 1
+and
+.Xr w3m 1 .
+I wrote a script
+to open images by piping
+.Xr curl 1
+into
+.Xr imv 1 ,
+videos with
+.Xr mpv 1 ,
+and everything else with
+.Xr w3m 1
+in a new
+.Xr xterm 1 .
+Annoyingly,
+.Xr mpv 1
+seems incapable of exiting
+without segfaulting.
+That's quality.
+.
+.Pp
+One thing I am still missing
+is automatic brightness adjustment
+based on ambient light
+like macOS can do.
+I can read the sensor with
+.Xr sysctl 8
+.Cm hw.sensors.asmc0.illuminance0 ,
+which is measured in lux.
+I tried doing something with it in a script,
+but it seems tricky to map its value
+to brightness adjustments
+and to play nice with manual brightness changes,
+so I'll just keep doing it manually for now.
+.
+.Pp
+Update:
+prx sent mail to let me know about
+.Aq Lk https://github.com/jcs/xdimmer .
+I should've guessed jcs had written something.
+.
+.Pp
+And that's my current
+.Ox
+setup after a week of using it.
+I'm quite enjoying it,
+and still being pleasantly surprised
+by the quality-of-life from
+.Ox
+tools and documentation.
+For a small example,
+I can jump to sections
+or flag definitions in
+.Xr man 1
+using
+.Ic :t .
+Systems without basic usability like that
+should be ashamed.
+.
+.Pp
+I would post a screenshot,
+but this is
+.Li text.causal.agency
+;)
+.
+.Sh SEE ALSO
+.Lk https://gist.github.com/jcs/5573685
+.Pp
+My full configurations are in
+.Aq Lk https://git.causal.agency/src .
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
+.
+.Sh BUGS
+There's a red LED
+inside the headphone jack
+that is always on
+and I have no idea how to turn off.
+If anyone knows
+please send me an email.
diff --git a/www/text.causal.agency/017-unpasswords.7 b/www/text.causal.agency/017-unpasswords.7
new file mode 100644
index 00000000..f9643f2f
--- /dev/null
+++ b/www/text.causal.agency/017-unpasswords.7
@@ -0,0 +1,153 @@
+.Dd February 20, 2021
+.Dt UNPASSWORDS 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Unpasswords
+.Nd password anti-management
+.
+.Sh DESCRIPTION
+Right away I want to say
+that I'm not trying to tell anyone
+how to manage their online authentication.
+This is just how I do it,
+and I haven't seen anyone else write about it.
+.
+.Pp
+I don't use a password manager.
+It's not a type of software
+I want to deal with.
+For the small handful of sites
+that I use regularly
+and that actually matter,
+I use strong passwords
+(stored in my noggin)
+and TOTP.
+For everything else,
+I simply do not know the password,
+and neither does any software.
+.
+.Pp
+I think I started doing this one time
+when I had legitimately forgotten
+the password to some old account.
+I clicked on
+.Dq forgot my password
+and opened the email,
+but I didn't want to
+come up with a new password
+I would just forget again.
+Instead I set a random one
+.Po
+I usually use
+.Ql openssl rand -base64 33
+for this
+.Pc
+and immediately used that to log in
+while it was still in my clipboard.
+Next time I wanted to log in,
+I could use
+.Dq forgot my password
+again.
+.
+.Pp
+Thinking about it,
+I realized that any web authentication
+with an email password reset flow
+is only ever as strong as
+the authentication for your email account.
+So what is the point of having
+all these passwords set on different sites?
+They all answer to your email account,
+and storing them in a password manager
+seems to add another potential point of failure.
+May as well have no other passwords at all,
+or as close as possible.
+.Po
+Shout out to sites like Liberapay
+and asciienema
+which let me not set a password at all.
+.Pc
+.
+.Pp
+So I started doing that for any site
+that I don't regularly log in to.
+Going through the password reset flow
+can be a bit slow,
+but it doesn't need to be done often.
+And I can do it from anywhere
+I have access to my email,
+which I feel is more easily reliable
+than syncing password management databases.
+It's quite stress-free.
+.
+.Pp
+After doing this manually for years,
+this week I finally got around to
+writing some automation for it.
+A while ago I had written
+.Xr imbox 1 ,
+a tool to directly export mail
+in mboxrd format from IMAP,
+along with
+.Xr git-fetch-email 1 ,
+a wrapper which offloads configuration to
+.Xr git-config 1 .
+It can match emails by
+Subject, From, To and Cc.
+This week I added a flag
+to use IMAP IDLE
+to wait for a matching message
+if there isn't one already,
+and a flag to move matching messages
+(for example to Trash)
+after exporting them.
+.
+.Pp
+With those two new flags,
+I started writing some shell scripts
+to automate the password reset flow
+using
+.Xr curl 1
+to submit forms and
+.Xr git-fetch-email 1
+with
+.Xr sed 1
+to pull the reset tokens
+from my inbox.
+At the end of the script,
+the random password it set
+is copied to the clipboard
+and the login page for the site is opened.
+So now logging in is as simple
+as running a command,
+waiting for the login page to open,
+and pasting.
+.
+.Pp
+The script isn't sophisticated,
+but I don't think it needs to be.
+I've written functions
+for a couple different sites already,
+and they all work in mostly the same way.
+Writing a new one is just a matter
+of identifying the form URLs and fields
+along with where the token is in the email.
+I'm not going to turn this automation
+into any kind of generally usable project,
+because I don't want to have to
+maintain functions for tonnes of different services.
+If you're interested in this idea,
+I encourage you to use my script as a template
+and implement the functions for services you use.
+.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Lk https://git.causal.agency/imbox
+.It
+.Lk https://causal.agency/bin/sup.html
+.El
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/018-operating-systems.7 b/www/text.causal.agency/018-operating-systems.7
new file mode 100644
index 00000000..691102e2
--- /dev/null
+++ b/www/text.causal.agency/018-operating-systems.7
@@ -0,0 +1,86 @@
+.Dd February 22, 2021
+.Dt OPERATING-SYSTEMS 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Operating systems
+.Nd criteria
+.
+.Sh DESCRIPTION
+Sometimes in conversation
+I use the term
+.Dq real operating system
+which people,
+perhaps rightfully,
+take as inflammatory.
+But I have actually thought about
+what I mean when I say
+.Dq real operating system
+and come up with
+this list of criteria.
+.
+.Pp
+An operating system should be...
+.Bl -bullet
+.It
+Consistent and cohesive:
+all parts of the system should have similar
+usage, configuration, documentation and so on.
+Parts of the system should naturally work together,
+because they were designed to do so.
+.
+.It
+Documented:
+the system should include its own documentation.
+A user should not have to
+search some external wiki
+to learn how the system works.
+It should be obvious
+where to find documentation
+on a particular topic.
+.
+.It
+Programmable:
+the system should provide
+a way to program the computer.
+A computer which cannot be programmed
+is not a computer at all.
+Usually this takes the form
+of a C compiler
+and the tools that go with it.
+In earlier times,
+it might have been
+a BASIC interpreter.
+.
+.It
+Examinable and modifiable:
+the full source tree
+for the system should be included,
+or easily obtainable
+through official means.
+A user should have no trouble
+finding the corresponding source
+for a part of the system.
+Together with the previous point,
+the source tree should be
+compiled by the included toolchain,
+allowing local modification.
+.El
+.
+.Pp
+Some things that may be parts
+of real operating systems,
+but are not themselves operating systems:
+a kernel,
+a package manager,
+a collection of packages.
+.
+.Pp
+I will leave it as an
+.Dq exercise for the reader
+to guess which operating systems
+meet these criteria
+and which don't.
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/019-mailing-list.7 b/www/text.causal.agency/019-mailing-list.7
new file mode 100644
index 00000000..3c70b160
--- /dev/null
+++ b/www/text.causal.agency/019-mailing-list.7
@@ -0,0 +1,287 @@
+.Dd March  4, 2021
+.Dt MAILING-LIST 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Mailing List
+.Nd a small-scale approach
+.
+.Sh DESCRIPTION
+When I initially published
+some software I expected
+other people to use,
+I just asked that patches
+be mailed directly to me,
+but I figured that
+if more people were interested,
+it would be better
+to have a mailing list.
+Unfortunately
+email software,
+mailing list options in particular,
+are quite daunting.
+I wanted a light-weight option
+that would require me to host
+as little software as possible.
+.
+.Pp
+My regular email is hosted by Fastmail,
+and I poked around its settings
+to see what I could do.
+It turns out Fastmail lets you
+configure address aliases to
+.Dq also send to all contacts in
+a contacts group.
+That's a mailing list!
+I created a group called
+.Dq List
+and an alias called
+.Mt list@causal.agency
+configured to deliver to that group.
+So it's really just an alias
+for my regular address
+that happens to also
+deliver to another group of people.
+.
+.Pp
+It's easier to just configure
+and manage one mailing list,
+so what I do is ask patches and feedback
+to be sent to
+.Mt list+catgirl@causal.agency ,
+for example.
+Fastmail treats any
+.Ar +suffix
+the same as the base address,
+but the full address can be used
+by subscribers to filter mail by topic
+if they wish.
+.
+.Pp
+To subscribe someone to the list,
+I add their contact to the group.
+For a long time I was planning
+to write some software
+to manage these subscriptions.
+It should be possible
+to process subscription requests from IMAP
+and manipulate the contact group with CardDAV.
+When I went to start implementing this,
+however,
+I found CardDAV (and WebDAV in general)
+completely inscrutable.
+It's the kind of protocol
+that is split across like 20
+different RFCs
+and you can't understand anything
+by just reading
+the one you actually care about.
+So I've given up on that
+and will keep manually subscribing people
+on request.
+.
+.Pp
+The only thing missing, then,
+is a way for people to read
+mail sent to the list
+while they aren't subscribed.
+All the existing
+mailing list archive software
+I know of
+expects to have the mail locally,
+but I'd rather keep all my mail in IMAP.
+First,
+in order to make sure
+I keep a complete archive
+of the mailing list in IMAP,
+I added a small amount
+of Sieve code
+to my Fastmail filters configuration:
+.Bd -literal -offset indent
+if address :matches ["To", "Cc"] "list*@causal.agency" {
+	fileinto :copy :flags "\e\eSeen" "INBOX.List";
+}
+.Ed
+.
+.Pp
+Sieve is a small standard language
+specifically for filtering mail.
+This bit of code matches
+anything sent to the list
+and adds a copy of it
+(the original is going into my inbox)
+to the
+.Dq List
+folder
+and marks the copy as read.
+.
+.Pp
+With a pristine IMAP mailbox
+to export from,
+I wrote a new archive generator.
+It's called
+.Xr bubger 1
+kirg (have it in a way).
+My goal was to render directly from IMAP
+and produce only static files as output,
+making it not only easy to serve,
+but also to run in one place
+and copy the files elsewhere.
+That's important to me
+because it has access to my email,
+so I'd rather run it
+on my local network and
+.Xr rsync 1
+its output into The Cloud.
+The static files are in
+HTML, Atom and mboxrd formats.
+.
+.Pp
+The architecture of
+.Xr bubger 1
+is that for each piece of mail,
+identified by its UID in the mailbox,
+HTML and Atom fragments
+are exported along with the mboxrd.
+Those fragments are then stitched together
+using the IMAP SORT and THREAD extensions
+to make full pages and feeds
+for each thread.
+The fragments act as a cache
+for subsequent runs.
+.
+.Pp
+I admit I did some
+pretty questionable things
+to achieve this.
+Namely,
+I wrote a small string templating engine in C.
+I use it to produce the HTML
+and XML for Atom,
+as well as to generate URLs
+and paths.
+I'm really happy with how it works, actually.
+This is also where
+I really started using
+one of my favourite C hacks:
+.Bd -literal -offset indent
+#define Q(...) #__VA_ARGS__
+.Ed
+.
+.Pp
+I quote all my HTML/XML templates
+with this and it's lovely.
+.
+.Pp
+I've been working on
+.Xr bubger 1
+on and off for almost a year now,
+and it's been interesting.
+I learned a lot about how email
+works from having to deal with
+all the ways a message can be.
+Thankfully a lot of that dealing
+is done by the IMAP server.
+.
+.Pp
+As for running it,
+I initially just ran it with
+.Xr cron 8 ,
+and that's still a good way to go.
+To hook it up to
+.Xr rsync 1 ,
+pipe it like so:
+.Bd -literal -offset indent
+bubger -C list [...] | rsync -a --files-from=- list remote:list
+.Ed
+.
+.Pp
+Later,
+I got a little annoyed
+with having to wait
+for the next run
+if I wanted to link
+to some mail I just received.
+I added an option
+to use IMAP IDLE
+to wait for new mail continuously
+and I started running it
+under my process supervisor,
+.Xr catsitd 8 .
+.
+.Pp
+The setup is a little more complex
+to feed the list of updated files to
+.Xr rsync 1 .
+I added the
+.Xr catsit-watch 1
+utility to run a command
+when a file changes,
+and in my
+.Xr catsit.conf 5
+I have the following:
+.Bd -literal -offset indent
+bubger	~/.local/libexec/bubger
+rsync	catsit-watch -i -f ~/list/UIDNEXT ~/.local/libexec/rsync
+.Ed
+.
+.Pp
+The
+.Pa ~/.local/libexec/bubger
+script runs
+.Xr bubger 1 ,
+writing the list of updated paths to
+.Pa ~/list/FILES ,
+truncating it before each update:
+.Bd -literal -offset indent
+exec bubger -it -C ~/list [...] >~/list/FILES
+.Ed
+.
+.Pp
+And the
+.Pa ~/.local/libexec/rsync
+script gets run each time a
+.Xr bubger 1
+update completes
+.Po
+.Pa UIDNEXT
+is always the last file written
+.Pc
+and copies the listed files
+to the remote host:
+.Bd -literal -offset indent
+exec rsync -a --files-from=$HOME/list/FILES ~/list remote:list
+.Ed
+.
+.Pp
+I haven't tagged any
+.Xr bubger 1
+releases yet
+because it hasn't gotten
+a huge amount of testing,
+and I'm not sure anyone but me
+would even want to use it.
+But I'm happy
+with how it's working right now,
+so I might tag 1.0 soon
+just for fun.
+.
+.Sh SEE ALSO
+.Bl -item -compact
+.It
+.Lk https://causal.agency/list/
+.It
+.Lk https://git.causal.agency/bubger/about
+.It
+.Lk https://git.causal.agency/catsit/about
+.El
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
+.
+.Sh BUGS
+Almost every time
+I try to type
+.Dq mailing list
+I instead type
+.Dq mailist list .
diff --git a/www/text.causal.agency/020-c-style.7 b/www/text.causal.agency/020-c-style.7
new file mode 100644
index 00000000..9816dbc3
--- /dev/null
+++ b/www/text.causal.agency/020-c-style.7
@@ -0,0 +1,172 @@
+.Dd March 16, 2021
+.Dt C-STYLE 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm C Style
+.Nd a rough description
+.
+.Sh DESCRIPTION
+This is a rough description
+of the style in which I write C,
+since it's uncommon
+but some people seem to like it.
+I don't have any hard rules,
+it just needs to look right.
+.
+.Ss Superficialities
+I use tabs
+and they're set to 4 characters wide
+in my editor.
+I keep my lines shorter than 80 columns,
+which I enforce by
+not resizing my terminal's width.
+I use block indentation only,
+meaning I write long function calls
+like this:
+.Bd -literal -offset indent
+fprintf(
+    imap.w, "%s UID THREAD %s UTF-8 %s\er\en",
+    Atoms[thread], algo, search
+);
+.Ed
+.Pp
+Anything that can be sorted
+should be sorted,
+with trailing commas where possible.
+This and block indentation
+make for simpler diffs.
+.Pp
+I either write single-line ifs
+or always use braces.
+I put parentheses
+around ternary expressions.
+I use camelCase
+for functions and variables,
+and PascalCase for types and constants.
+When an acronym appears
+in an identifier,
+it's in either all lower case
+or all upper case.
+The despicable SCREAMING_SNAKE_CASE
+is reserved for macros.
+I don't set globals or statics to zero
+since that is already the default.
+I don't compare against zero or NULL
+unnecessarily.
+.
+.Ss \&No side-effects in control flow
+I never write a function call
+with side-effects
+inside the condition of an if statement.
+I find this makes following the
+.Dq happy path
+through functions
+much easier.
+I write things like this:
+.Bd -literal -offset indent
+pidFile = open(pidPath, O_WRONLY | O_CREAT | O_CLOEXEC, 0600);
+if (pidFile < 0) err(EX_CANTCREAT, "%s", pidPath);
+
+error = flock(pidFile, LOCK_EX | LOCK_NB);
+if (error && errno != EWOULDBLOCK) err(EX_IOERR, "%s", pidPath);
+if (error) errx(EX_CANTCREAT, "%s: file is locked", pidPath);
+.Ed
+.Pp
+I do write side-effects
+inside for and while statement heads,
+since that's generally expected.
+For some reason
+I like to write the constant first
+if I'm comparing the result of an assignment
+with a side-effect.
+.Bd -literal -offset indent
+for (ssize_t len; 0 <= (len = getline(&buf, &cap, file)); ++line)
+.Ed
+.
+.Ss Paragraphs
+I leave blank lines
+between logical chunks of
+.Dq things happening .
+This is usually between side-effects
+with their related error handling,
+or between groups of closely related side-effects.
+I try to keep variable declarations
+glued to the top of the bit of code
+they're used in.
+.
+.Ss Leading break
+I've mentioned this previously.
+I write my switch statement breaks
+before each case label.
+Doing this aligns nicely,
+and being in the habit
+means I always avoid
+accidental fallthrough.
+.Bd -literal -offset indent
+switch (opt) {
+    break; case 'a': append = 1;
+    break; case 'd': delay = strtol(optarg, NULL, 10);
+    break; case 'f': watch(kq, optarg);
+    break; case 'i': init = 1;
+    break; default: return EX_USAGE;
+}
+.Ed
+.
+.Ss Function type definitions
+Function types are always typedef'd,
+and it's the function type itself
+that is defined,
+not a function pointer type!
+I put the typedef above any functions
+that are supposed to be of that type
+so it's clear what the pattern is.
+.Bd -literal -offset indent
+typedef void Action(struct Service *service);
+Action *fn = NULL;
+.Ed
+.
+.Ss Constants
+I prefer enums over #defines
+for integer constants,
+and static const strings over #defines
+unless I want to do concatenation.
+.Bd -literal -offset indent
+enum { Cap = 1024 };
+.Ed
+.Pp
+I avoid the preprocessor
+wherever possible,
+with the notable exception of X macros,
+which I've talked about previously.
+Doing things in the actual language
+makes for easier debugging.
+.
+.Ss Organization
+I usually use only one header file
+in each project.
+The dependency is easy to declare
+and the complete rebuild
+when the header changes
+isn't a problem for small projects.
+Unless it's a single-file program,
+I name the file which contains main
+something generic,
+since the name of the project
+isn't relevant to its function.
+I name functions like
+.Ar nounVerb ,
+and all the functions for a 
+.Ar noun
+are defined in
+.Pa noun.c .
+Not really to do with C,
+but I always put a FILES section
+in my README pages
+to briefly describe
+the layout of the code
+for anyone looking to
+read or make changes to it.
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
diff --git a/www/text.causal.agency/021-time-machine.7 b/www/text.causal.agency/021-time-machine.7
new file mode 100644
index 00000000..93d35c1e
--- /dev/null
+++ b/www/text.causal.agency/021-time-machine.7
@@ -0,0 +1,144 @@
+.Dd April 25, 2021
+.Dt TIME-MACHINE 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Time Machine
+.Nd an awful one
+.
+.Sh DESCRIPTION
+If, like me,
+you have a Raspberry Pi 3 at home
+that you've just upgraded to
+.Fx 13.0
+which has a hard drive
+from an old laptop
+attached to it by USB adapter
+with ZFS on it
+and you want to
+use that as a Time Machine
+backup destination
+over SMB using
+.Xr samba 8 ,
+despite
+.Xr samba 8
+being awful software
+and using ZFS on a system
+with only 1 GB of RAM
+being a terrible idea,
+this is how to do it.
+.
+.Pp
+In
+.Pa /usr/local/etc/smb4.conf :
+.Bd -literal -offset indent
+[global]
+vfs objects = zfsacl catia fruit streams_xattr
+fruit:metadata = stream
+fruit:model = Macmini
+
+[TimeMachine]
+read only = no
+path = /media/zhdd/backup/TimeMachine
+fruit:time machine = yes
+fruit:time machine max size = 250G
+.Ed
+.
+.Pp
+The important thing here is
+.Sy zfsacl
+in the vfs objects list.
+Most pages will tell you about the others,
+but without
+.Sy zfsacl
+Time Machine will just fail to
+create the backup
+and not provide any useful error.
+I'm not actually sure if the
+.Sy fruit:metadata
+setting is required,
+but a bunch of pages recommend it.
+The
+.Sy fruit:model
+just makes it look nice in Finder.
+The rest creates an SMB share called
+.Dq TimeMachine
+that macOS will be willing to use.
+You can limit the size of the share that
+.Xr samba 8
+reports so that Time Machine
+doesn't fill up the whole drive.
+.
+.Pp
+The other important thing to do
+is to create some swap space.
+When I first tried backing up
+to this share,
+it stopped after a while
+because
+.Xr smbd 8
+got killed
+when there was nowhere to swap pages to.
+A wiki page told me to
+create swap on ZFS like this:
+.Bd -literal -offset indent
+zfs create -V 2G \e
+	-o org.freebsd:swap=on \e
+	-o checksum=off \e
+	-o compression=off \e
+	-o dedup=off \e
+	-o sync=disabled \e
+	-o primarycache=none \e
+	zhdd/swap
+swapon /dev/zvol/zhdd/swap
+.Ed
+.
+.Pp
+To be fair to
+.Xr samba 8 ,
+most of the memory
+is being used by the ZFS ARC
+.Po
+which you can see in
+.Xr top 1
+.Pc ,
+but
+.Xr smbd 8
+still seems to be using
+far more memory than is reasonable.
+It's interesting seeing processes
+with 0 RES in
+.Xr htop 1
+because they're all being swapped out
+while the ARC takes half the available RAM.
+And having to wait for my shell
+to be paged back in when I quit
+.Xr htop 1 .
+.
+.Pp
+Anyway,
+as expected this whole thing
+is terribly slow.
+On my initial backup,
+I'm currently at 26.49 GB
+of 104.22 GB
+with an estimate of 8 hours remaining.
+Normally transfer time estimates
+are wildly inaccurate,
+but I think in this case it's right.
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
+.
+.Sh BUGS
+.Fx
+doesn't seem to want to mount
+the ZFS volumes on the hard-drive-over-USB
+automatically at boot.
+I have to
+.Xr zpool-import 8
+the drive manually each time.
+I don't know if there's a workaround for this,
+but I don't have anything essential
+to the system on the drive,
+and it doesn't need to reboot often.
diff --git a/www/text.causal.agency/022-swans-are-dead.7 b/www/text.causal.agency/022-swans-are-dead.7
new file mode 100644
index 00000000..8664e886
--- /dev/null
+++ b/www/text.causal.agency/022-swans-are-dead.7
@@ -0,0 +1,164 @@
+.Dd May  5, 2021
+.Dt SWANS-ARE-DEAD 7
+.Os "Causal Agency"
+.
+.Sh NAME
+.Nm Swans Are Dead
+.Nd album by Swans
+.
+.Sh DESCRIPTION
+Swans Are Dead
+is the best Swans album.
+Among my favourites are
+Soundtracks for the Blind,
+To Be Kind
+and Love of Life,
+but Swans Are Dead
+is the one I come back to
+most consistently.
+I'm always in the mood
+to listen to these tunes.
+.
+.Pp
+It's interesting to me
+that I enjoy it so much,
+I think because I had the expectation
+that live albums
+are not of the same quality
+as studio albums,
+but that's just completely untrue
+in the case of Swans.
+The performances are excellent
+and the recording is
+for the most part perfect.
+The album feels live,
+without any distracting deficiencies
+of live recording
+that would take you out
+of just enjoying the music.
+.
+.Bl -ohang
+.It Dq Feel Happiness
+This track feels kind of special
+since it's the only song on the album
+that was never released
+as part of another project.
+I absolutely love this format of song.
+It's like 10 minutes of build
+before any lyrics happen,
+which you only get after
+the wave of the first part
+of the song collapses.
+It bookends the first disc nicely with
+.Dq Blood Promise,
+I think,
+which is sort of the reverse.
+.
+.It Dq Blood On Yr Hands
+This is such a great start
+to the Jarboe-focused
+section of the black disc.
+A cappella apart from the hum
+of the equipment on stage,
+I love this vocal performance.
+I sing this song,
+terribly,
+in the shower.
+The lack of instrumental
+seems to make it stick in my mind even more.
+.
+.It Dq I Crawled
+This is another great vocal performance
+by Jarboe.
+It's so much more dynamic and intense
+than the version of this song
+released much earlier on Young God
+with Gira's vocals.
+I remember seeing a bad comment
+somewhere online
+from someone who couldn't stand
+any Swans song Jarboe sang on.
+They must have never heard
+this version of
+.Dq I Crawled.
+Incredible.
+.
+.It Dq Blood Promise
+My favourite track on
+Swans Are Dead,
+by far.
+I had actually never heard of
+.Dq The Whiffenpoof Song
+until I looked up
+the recording they use
+to introduce this song
+and indicate it's the last of the show.
+Anyway,
+this track highlights
+what makes Swans live albums
+so interesting.
+This performance of the song
+has evolved so much
+from the studio recording on
+The Great Annihilator.
+They share the same lyrics,
+but the earlier version is only 4:15,
+to the live version's fifteen and a half minutes!
+And it sucks me in the whole time.
+As the song winds down
+you can hear an audience member yell,
+.Dq Don't stop!
+and I agree.
+.
+.It Dq The Sound
+One of my all-time favourite songs.
+It's the one that got me to listen to
+Soundtracks for the Blind,
+and might've gotten me into Swans altogether.
+I don't quite remember
+what order I started listening to things in.
+This version of it is great.
+I don't think I could choose
+between this and the studio recording.
+There are just
+two ways to enjoy it.
+I love how frantic the guitars get
+at the height of this track.
+.
+.It Dq I See Them All Lined Up
+This version of the song
+is way more harsh
+than the version on Soundtracks.
+It loses some contrast
+between the verses
+and the explosions of sound
+punctuating them,
+it just hits hard
+the whole time.
+.
+.It Dq Yum Yab
+An absolute banger.
+The drums sound so good on this
+and they really get me moving.
+The whole thing is delightfully nasty and fun.
+.El
+.
+.Pp
+Everything else on the album
+is good too,
+of course,
+I just don't have as much to say.
+There's almost two and a half hours of music
+on this thing!
+.
+.Sh AUTHORS
+.An june Aq Mt june@causal.agency
+.Pp
+I want to try writing
+about different kinds of things here,
+and this is my first attempt
+at doing so.
+There's more music
+I want to write about,
+and maybe some other
+non-computer topics.
diff --git a/www/text.causal.agency/Makefile b/www/text.causal.agency/Makefile
new file mode 100644
index 00000000..192bb272
--- /dev/null
+++ b/www/text.causal.agency/Makefile
@@ -0,0 +1,47 @@
+WEBROOT ?= /usr/local/www/text.causal.agency
+LIBEXEC ?= /usr/local/libexec
+
+CFLAGS += -Wall -Wextra
+
+TXTS += 001-make.txt
+TXTS += 002-writing-mdoc.txt
+TXTS += 003-pleasant-c.txt
+TXTS += 004-uloc.txt
+TXTS += 005-testing-c.txt
+TXTS += 006-some-libs.txt
+TXTS += 007-cgit-setup.txt
+TXTS += 008-how-irc.txt
+TXTS += 009-casual-update.txt
+TXTS += 010-irc-suite.txt
+TXTS += 011-libretls.txt
+TXTS += 012-inability.txt
+TXTS += 013-hot-tips.txt
+TXTS += 014-using-vi.txt
+TXTS += 015-reusing-tags.txt
+TXTS += 016-using-openbsd.txt
+TXTS += 017-unpasswords.txt
+TXTS += 018-operating-systems.txt
+TXTS += 019-mailing-list.txt
+TXTS += 020-c-style.txt
+TXTS += 021-time-machine.txt
+TXTS += 022-swans-are-dead.txt
+
+all: ${TXTS}
+
+.SUFFIXES: .7 .txt
+
+.7.txt:
+	mandoc -T utf8 $< | col -bx > $@
+
+feed.atom: feed.sh ${TXTS}
+	sh feed.sh > feed.atom
+
+clean:
+	rm -f ${TXTS} feed.atom igp
+
+install: ${TXTS} feed.atom
+	install -p -m 644 ${TXTS} feed.atom ${WEBROOT}
+
+install-igp: igp
+	install igp ${LIBEXEC}
+	install -p -m 644 igp.c ${WEBROOT}
diff --git a/www/text.causal.agency/feed.sh b/www/text.causal.agency/feed.sh
new file mode 100644
index 00000000..f45bd326
--- /dev/null
+++ b/www/text.causal.agency/feed.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+set -eu
+
+readonly Root='https://text.causal.agency'
+
+updated=$(date -u '+%FT%TZ')
+cat <<-EOF
+	<?xml version="1.0" encoding="utf-8"?>
+	<feed xmlns="http://www.w3.org/2005/Atom">
+	<title>Causal Agency</title>
+	<author><name>June</name><email>june@causal.agency</email></author>
+	<link href="${Root}"/>
+	<link rel="self" href="${Root}/feed.atom"/>
+	<id>${Root}/</id>
+	<updated>${updated}</updated>
+EOF
+
+encode() {
+	sed '
+		s/&/\&amp;/g
+		s/</\&lt;/g
+		s/"/\&quot;/g
+	' "$@"
+}
+
+for txt in *.txt; do
+	entry="${txt%.txt}.7"
+	date=$(grep '^[.]Dd' "$entry" | cut -c 5-)
+	title=$(grep '^[.]Nm' "$entry" | cut -c 5- | encode)
+	summary=$(grep '^[.]Nd' "$entry" | cut -c 5- | encode)
+	published=$(date -ju -f '%B %d, %Y %T' "${date} 00:00:00" '+%FT%TZ')
+	mtime=$(stat -f '%m' "$entry")
+	updated=$(date -ju -f '%s' "$mtime" '+%FT%TZ')
+	cat <<-EOF
+		<entry>
+		<title>${title}</title>
+		<summary>${summary}</summary>
+		<link href="${Root}/${txt}"/>
+		<id>${Root}/${txt}</id>
+		<published>${published}</published>
+		<updated>${updated}</updated>
+		<content type="xhtml">
+		<div xmlns="http://www.w3.org/1999/xhtml">
+	EOF
+	printf '<pre>'
+	encode "$txt"
+	cat <<-EOF
+		</pre>
+		</div>
+		</content>
+		</entry>
+	EOF
+done
+
+echo '</feed>'
diff --git a/www/text.causal.agency/igp.1 b/www/text.causal.agency/igp.1
new file mode 100644
index 00000000..ccfaeaa6
--- /dev/null
+++ b/www/text.causal.agency/igp.1
@@ -0,0 +1,49 @@
+.Dd January 14, 2021
+.Dt IGP 1
+.Os
+.
+.Sh NAME
+.Nm igp
+.Nd insane gopher posse
+.
+.Sh SYNOPSIS
+.Nm
+.Op Fl h Ar host
+.Op Fl p Ar port
+.Ar directory
+.
+.Sh DESCRIPTION
+The
+.Nm
+utility is a simple
+Internet Gopher server
+which can be started by
+.Xr inetd 8 .
+It serves directory listings
+and files under
+.Ar directory .
+.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl h Ar host
+Set the host used in directory listings.
+The default is the local host name.
+.It Fl p Ar port
+Set the port used in directory listeings.
+The default is port 70.
+.El
+.
+.Sh STANDARDS
+.Rs
+.%A B. Alberti
+.%A F. Anklesaria
+.%A D. Johnson
+.%A P. Lindner
+.%A M. McCahill
+.%A D. Torrey
+.%T The Internet Gopher Protocol
+.%I IETF
+.%R RFC 1436
+.%D March 1993
+.Re
diff --git a/www/text.causal.agency/igp.c b/www/text.causal.agency/igp.c
new file mode 100644
index 00000000..cda604d8
--- /dev/null
+++ b/www/text.causal.agency/igp.c
@@ -0,0 +1,143 @@
+/* Copyright (C) 2021  June McEnroe <june@causal.agency>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#ifdef __FreeBSD__
+#include <sys/capsicum.h>
+#endif
+
+static int compar(const void *_a, const void *_b) {
+	const struct dirent *a = _a;
+	const struct dirent *b = _b;
+	if (a->d_type != b->d_type) {
+		return (a->d_type > b->d_type) - (a->d_type < b->d_type);
+	}
+	return strcmp(a->d_name, b->d_name);
+}
+
+int main(int argc, char *argv[]) {
+	int error;
+	const char *host = NULL;
+	const char *port = "70";
+	for (int opt; 0 < (opt = getopt(argc, argv, "h:p:"));) {
+		switch (opt) {
+			break; case 'h': host = optarg;
+			break; case 'p': port = optarg;
+			break; default:  return EX_USAGE;
+		}
+	}
+	if (optind == argc) return EX_USAGE;
+	if (!host) {
+		static char buf[256];
+		error = gethostname(buf, sizeof(buf));
+		if (error) abort();
+		host = buf;
+	}
+
+	const char *path = argv[optind];
+	int root = open(path, O_RDONLY | O_DIRECTORY);
+	if (root < 0) err(EX_NOINPUT, "/");
+
+#ifdef __FreeBSD__
+	cap_rights_t cap;
+	error = cap_enter()
+		|| cap_rights_limit(STDIN_FILENO, cap_rights_init(&cap, CAP_READ))
+		|| cap_rights_limit(STDOUT_FILENO, cap_rights_init(&cap, CAP_WRITE))
+		|| cap_rights_limit(STDERR_FILENO, &cap)
+		|| cap_rights_limit(
+			root, cap_rights_init(&cap, CAP_PREAD, CAP_FSTATAT, CAP_FSTATFS)
+		);
+	if (error) abort();
+#else
+#warning "This is completely insecure without capsicum(4)!"
+#endif
+
+	char buf[1024];
+	if (!fgets(buf, sizeof(buf), stdin)) return EX_PROTOCOL;
+	char *ptr = buf;
+	char *sel = strsep(&ptr, "\t\r\n");
+	if (sel[0] == '/') sel++;
+
+	int fd = (sel[0] ? openat(root, sel, O_RDONLY) : root);
+	if (fd < 0) err(EX_NOINPUT, "%s", sel);
+
+	struct stat stat;
+	error = fstat(fd, &stat);
+	if (error) err(EX_IOERR, "%s", sel);
+	if (!(stat.st_mode & (S_IFREG | S_IFDIR))) {
+		errx(EX_NOINPUT, "%s: Not a file or directory", sel);
+	}
+
+	if (stat.st_mode & S_IFREG) {
+#ifdef __FreeBSD__
+		error = sendfile(fd, STDOUT_FILENO, 0, 0, NULL, NULL, 0);
+		if (!error) return EX_OK;
+#endif
+		char buf[4096];
+		for (ssize_t len; 0 < (len = read(fd, buf, sizeof(buf)));) {
+			fwrite(buf, len, 1, stdout);
+		}
+		return EX_OK;
+	}
+
+	DIR *dir = fdopendir(fd);
+	if (!dir) err(EX_IOERR, "%s", sel);
+
+	size_t len = 0;
+	size_t width = 0;
+	static struct dirent ents[4096];
+	for (struct dirent *ent; len < 4096 && (ent = readdir(dir));) {
+		if (ent->d_name[0] == '.') continue;
+		if (ent->d_type != DT_REG && ent->d_type != DT_DIR) continue;
+		if (ent->d_namlen > width) width = ent->d_namlen;
+		ents[len++] = *ent;
+	}
+
+	qsort(ents, len, sizeof(ents[0]), compar);
+	for (size_t i = 0; i < len; ++i) {
+		char mtime[26] = "";
+		if (ents[i].d_type == DT_REG) {
+			error = fstatat(fd, ents[i].d_name, &stat, 0);
+			if (error) err(EX_IOERR, "%s/%s", sel, ents[i].d_name);
+			ctime_r(&stat.st_mtime, mtime);
+			mtime[24] = '\0';
+		}
+		printf(
+			"%c%-*s  %s\t%s%s%s\t%s\t%s\r\n",
+			(ents[i].d_type == DT_DIR ? '1' : '0'),
+			(int)width, ents[i].d_name, mtime,
+			sel, (sel[0] ? "/" : ""), ents[i].d_name, host, port
+		);
+	}
+
+	printf("i-- \t\t%s\t%s\r\n", host, port);
+	printf("0Served by IGP (AGPLv3)\tigp.c\ttext.causal.agency\t70\r\n");
+	printf(".\r\n");
+}